C# 何时可以处置IDisposable WPF控件,例如WindowsFormsHost?

C# 何时可以处置IDisposable WPF控件,例如WindowsFormsHost?,c#,.net,wpf,idisposable,C#,.net,Wpf,Idisposable,WPF控件WindowsFormsHost继承自IDisposable 如果我有一个复杂的WPF可视化树,其中包含上述一些控件,那么在关闭期间我可以使用什么事件或方法调用IDispose?关闭表单时不需要处理控件,如果控件位于表单的可视化树中(作为表单的子控件或表单中的其他控件),API将自动为您执行此操作在应用程序关闭的情况下,无需执行任何操作即可正确处理WindowsFormsHost。因为它源于HwndHost,所以在Dispatcher关闭时处理它。如果您使用Reflector,您将看到

WPF控件WindowsFormsHost继承自IDisposable


如果我有一个复杂的WPF可视化树,其中包含上述一些控件,那么在关闭期间我可以使用什么事件或方法调用IDispose?

关闭表单时不需要处理控件,如果控件位于表单的可视化树中(作为表单的子控件或表单中的其他控件),API将自动为您执行此操作

在应用程序关闭的情况下,无需执行任何操作即可正确处理WindowsFormsHost。因为它源于HwndHost,所以在Dispatcher关闭时处理它。如果您使用Reflector,您将看到当HwndHost初始化时,它会创建一个较弱的关机

如果您在对话框中使用它,我建议您最好覆盖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);
    }
}
测试何时调用dispose的一种简单方法是从WindowsFormsHost派生一个自定义类,并处理不同的情况。在dispose中放置一个断点,并查看它何时被调用

public class CustomWindowsFormsHost : WindowsFormsHost
{
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
}

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

(显然,如果您可以避免从IDisposable do继承,但有时您就是做不到)

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

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


WPF控件没有实现IDisposable接口,因为它们没有要处理的内容(没有要清理的句柄,没有要释放的非托管内存)。您所需要做的就是确保没有对控件的任何引用,并且GC将清除它们


因此,WPF使用来确保控件可以被垃圾收集。这是您需要实现的模式,以确保清理,而不是IDisposable。

My WFH是包含主WPF窗口的树中另一个WPF控件的子控件。永远不会调用WFH上的Dispose。在主wpf窗口上调用Dispose时,其所有子项都将被释放(依此类推)。您的WFH控件应该在没有任何额外工作的情况下在那时被释放。鉴于wpf应用程序类和wpf窗口类都不从IDisposable继承,这似乎不太可能-我相信wpf在您拉入winforms之前不需要释放。当您说“在关机期间”时,您的意思是应用程序正在被释放吗关闭控件不再可见?对话框正在关闭?这里我指的是应用程序关闭,但我也对对话框关闭的情况感兴趣。Thx听起来不错。对于带有应用程序的windowsformshost控件也是如此。我可以依靠hwdhost钩住调度程序关闭事件,对于一个对话框,我可以在我的控件中为对话框窗口的onclosed事件编写一个类似的钩子,我可以为一个通用IDisposable控件复制这两种模式。问题:你在dispose方法中做什么?取决于控件-通常你没有任何东西,但不幸的是,有一些特殊情况请参阅我对你答案的评论对于在Windows窗体应用程序中托管WPF的用户,将失败。还有更兼容的方法可以替代地连接到主窗体的关联WinForms close事件,但对于广泛可重用的WPF控件库来说,这是不够的。此外,仅在主窗口关闭时进行清理可能不是大多数开发人员想要的。相反,当树上的第一个窗口/页面超出范围时(不一定是关闭时),可能更希望进行清理谢谢-听起来你有一些有用的想法-如果你想提交一个答案,描述一个更好的和更一般的解决方案,那么我将高兴地取消选择这个答案,并考虑你的。通常你是正确的-但是,也有例外-作为一个例子,Windows窗体是一个WPF控件,并实现IDISPOLISTABLE。它确实有一个hwnd要处理,因为它承载winforms控件。如果您有要处理的内容,则实现IDisposable,如果您没有,则不实现。但是,在您执行之前不要实现它。在您交换现有控件并希望确保旧控件上的所有事件以及该控件处理的所有事件都被取消挂钩以便它们停止处理事件的情况下,弱事件模式似乎仍然会造成问题。在我们的实验中,这些事件似乎仍在继续。调用Dispose在WinForms中也用于此事件清理目的。
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();
                    };
                }
            };

            ...

        }

        ...
    }