我什么时候可以处理IDisposable WPF控件,例如WindowsFormsHost?

mor*_*lli 12 .net c# wpf idisposable

WPF控件WindowsFormsHost继承自IDisposable.

如果我有一个包含上述某些控件的复杂WPF可视树,我可以使用哪些事件或方法在关机期间调用IDispose?

Tod*_*ite 8

在应用程序关闭的情况下,您无需执行任何操作来正确处理WindowsFormsHost.由于它派生自HwndHost,因此在Dispatcher关闭时会处理.如果使用Reflector,您将看到在初始化HwndHost时它会创建一个WeakEventDispatcherShutdown.

如果你在一个对话框中使用它,我建议的最好是覆盖OnClosed然后处理你的主机,否则HwndHost会一直闲置直到Dispatcher关闭.

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

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

        base.OnClosed(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试dispose何时被调用的一种简单方法是从WindowsFormsHost派生自定义类并在不同情况下进行游戏.在处理中放置一个断点并查看它何时被调用.

public class CustomWindowsFormsHost : WindowsFormsHost
{
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
}
Run Code Online (Sandbox Code Playgroud)


mor*_*lli 4

根据 Todd 的回答,我为 Window 托管的任何 WPF 控件想出了这个通用解决方案,并希望保证在该窗口关闭时进行处理。

(显然,如果你可以避免从 IDisposable 继承,但有时你就是不能)

当层次结构中的第一个父窗口关闭时调用 Dispose。

(可能的改进 - 更改事件处理以使用弱模式)

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

            ...

        }

        ...
    }
Run Code Online (Sandbox Code Playgroud)

  • 对于那些在 Windows 窗体应用程序中托管 WPF 的人来说,这将失败。还有更兼容的方法也可以连接到主窗体的关联 WinForms 关闭事件,但正如您所拥有的那样,这对于广泛可重用的 WPF 控件库来说是不够的。仅在主窗口关闭时才进行清理可能并不是大多数开发人员想要的。相反,当树上的第一个窗口/页面超出范围时(不一定是在关闭时),可能更需要进行清理。 (2认同)