12
votes

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?

4
When you say 'during shutdown' do you mean the app is being closed? The control is no longer visible? A dialog is being closed?Todd White
Here I mean application shutdown, but I am also interested in the dialog closing case.morechilli

4 Answers

8
votes

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);
    }
}
4
votes

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();
                    };
                }
            };

            ...

        }

        ...
    }
-1
votes

You don't need to dispose controls when closing a form, the API will do it for you automatically if the control is in the visual tree of the form ( as a child of the form or other control in the form)

-1
votes

WPF Controls don't implement the IDisposable interface, because they have nothing to dispose (No handles to clean up, no unmanaged memory to release). All you need to do is make sure that you don't have any references to the controls and the GC will clean them.

Therefore WPF employs weak event patterns to ensure that controls can be garbage collected. This is the pattern you need to implement to ensure clean-up, not IDisposable.