【问题标题】:WPF parent-child window: binding reference problemWPF父子窗口:绑定引用问题
【发布时间】:2010-05-21 07:14:33
【问题描述】:

我有一个 WPF 窗口,它打开一个模式子窗口来加载一些数据。两个窗口都有自己的视图模型,现在我遇到了这个问题:关闭子窗口后,它似乎仍在后台运行!

为了关闭子窗口,我从 viewmodel 命令设置了 DialogResult;现在,如果我创建一个新数据,然后从父窗口编辑它(之前关闭子窗口),子窗口仍会捕获先前绑定的属性的属性更改事件。

如何避免这种情况?

当我关闭模式窗口时,我会用数据清除每个引用。最佳做法是什么?

【问题讨论】:

    标签: wpf binding window parent-child


    【解决方案1】:

    确保不要保留对窗口的任何引用,即使是间接引用。泄漏的最常见原因之一是事件。如果窗口 B 正在向窗口 A 的事件添加事件处理程序,则 B 不会被释放,直到 A 也被释放。

    例如,如果您直接监听属性更改,则应使用 Weak Event Pattern 并将所有 += 替换为对 PropertyChangedEventManager.AddListener 的调用。通常,您添加到事件中的每个强处理程序都应删除以避免泄漏。

    this MSDN article 中有关 .NET 泄漏的更多信息。

    您可以使用像 Scitech 的 mem profiler 或 Jetbrains dotTrace 这样的内存分析器来查看哪些项目将您的窗口保留在内存中。


    编辑:针对您的 cmets,您的情况确实比我最初想象的要简单:垃圾收集器根本还没有收集窗口。在Test_Click 上添加GC.Collect 用于测试目的可以解决问题。

    在这里,当表单关闭时从ComboBox 中删除SelectionChanged 事件,这样您就可以让GC 完成它的工作并在以后回收表单而不会出现问题。如果您确实需要立即发布整个表单,您可以考虑致电GC.Collect,尽管您应该尽可能避免使用它。

    编辑 2:响应您的第三条评论,它应该只对在视图之间共享的对象很重要,并且视图中的更改将在共享对象中更改回某些内容。在您的测试项目中,SelectionChanged 在原始列表中没有任何作用,因此是否引发事件并不重要。表单最终会被收集。

    【讨论】:

    • 我正在检查...我的实体实现了INotifyPropertyChanged接口,实体的一个属性与子win中ComboBox的SelectedValue绑定;后面的子窗口代码上的 ComboBox 有一个用于 SelectionChanged 的​​事件处理程序。然后,在我关闭子窗口后,如果我更改父窗口上的相同实体属性,则子窗口中 ComboBox 的 selectionchanged 事件处理程序正在触发。
    • 我创建了一个显示行为的愚蠢项目。您可以从 thi url 下载它:olisoft-olisistemi.it/uploads/WpfApplication2.zip 1) 单击“ChildWindow”按钮 2) 关闭 ChildWindow 3) 单击“Test”按钮 -> ChildWindow 中 ComboBox 的 SelectionChanged 事件触发!怎么了?弱事件模式是解决方案?
    • 谢谢,但如果我的 Window 后面的代码有更多事件,每次我都要删除所有处理程序关闭事件吗?还是有更好的方法?
    猜你喜欢
    • 1970-01-01
    • 2013-03-19
    • 2011-10-19
    • 1970-01-01
    • 2013-09-30
    • 1970-01-01
    • 2023-03-08
    • 2016-03-23
    • 2011-07-19
    相关资源
    最近更新 更多