Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When can I dispose an IDisposable WPF control e.g. WindowsFormsHost?

The WPF control WindowsFormsHost inherits from IDisposable.

If I have a complex WPF visual tree containing some of the above controls what event or method can I use to call IDispose during shutdown?

like image 453
morechilli Avatar asked Oct 31 '08 17:10

morechilli


2 Answers

In the case of application shutdown there is nothing you need to do to properly dispose of the WindowsFormsHost. Since it derives from HwndHost disposing is handled when the Dispatcher is shutdown. If you use Reflector you will see that when HwndHost is initialized it creates a WeakEventDispatcherShutdown.

If you are using it in a dialog the best I can suggest is to override OnClosed and dispose of your Host then, otherwise the HwndHost will hang around until until the Dispatcher is shutdown.

public partial class Dialog : Window
{
    public Dialog()
    {
        InitializeComponent();
    }

    protected override void OnClosed(EventArgs e)
    {
        if (host != null)
            host.Dispose();

        base.OnClosed(e);
    }
}

A simple way to test when dispose gets called is to derive a custom class from WindowsFormsHost and play around with different situations. Put a break point in dispose and see when it gets called.

public class CustomWindowsFormsHost : WindowsFormsHost
{
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
}
like image 121
Todd White Avatar answered Nov 20 '22 11:11

Todd White


Building from Todd's answer I came up with this generic solution for any WPF control that is hosted by a Window and want's to guarantee disposal when that window is closed.

(Obviously if you can avoid inheriting from IDisposable do, but sometimes you just can't)

Dispose is called when the the first parent window in the hierarchy is closed.

(Possible improvement - change the event handling to use the weak pattern)

public partial class MyCustomControl : IDisposable
    {

        public MyCustomControl() {
            InitializeComponent();

            Loaded += delegate(object sender, RoutedEventArgs e) {
                System.Windows.Window parent_window = Window.GetWindow(this);
                if (parent_window != null) {
                    parent_window.Closed += delegate(object sender2, EventArgs e2) {
                        Dispose();
                    };
                }
            };

            ...

        }

        ...
    }
like image 45
morechilli Avatar answered Nov 20 '22 11:11

morechilli