如何在View关闭时释放ViewModel?

时间:2014-05-27 13:25:08

标签: wpf mvvm

我们当前的应用程序将每个View包装成一个Window(这只是一个原型应用程序)。并且每个View / Window都有一个ViewModel被指定为DataContext。现在我的问题是,当ViewModel / Window关闭时,发布View的做法是什么?

我尝试处理Window的Closed事件,并将DataContext设置为NULL。我的ViewModelBase类实现了IDisposable接口。但是当我调试时,我发现没有调用Dispose()函数。当我使用内存分析器时,我发现ViewModel永远不会被释放。

那么发布ViewModel

的正确做法是什么?

更新:

两个潜在的内存泄漏源:

  1. 我正在使用IEventAggregator来做事件pub / sub。我正在使用Prism 4.1中的EventAggregator类,但只是将它包装在Singleton类中(它实现了IEventAggregator接口,因为我们还不想使用依赖注入)。
  2. ViewModel / View内,我只是使用(VB.NET中的代码)

    _ea.GetEvent(Of MyEventType).Publish(MyEventObject)
    _ea.GetEvent(Of MyEventType).Subscribe(AddressOr MyEventHandler)
    
    1. 我正在使用一些ActiveX控件。我正在测试的是使用来自OWC(Office Web Component)的数据透视表。而且我承认我不知道如何在MVVM世界中处理这种控制。我通常ViewModel直接拥有这样的控制成员,我认为这打破了MVVM的规则,这也是我目前只能对代码中的布线ViewModel进行硬编码的原因 - 在View
    2. 之后

      例如,在代码隐藏中,我有这样的行:

      Me.DataContext = New MyViewModel(Me.pTable)
      

      初始化DataContext

      ViewModel的构造函数中,我通常做两件事:

      a)设置/更改ActiveX控件的属性(在构造函数或函数中),如下所示:

      Me.pTable.DisplayDesignTimeUI = False
      

      b)处理来自ActiveX Control

      的事件
      AddHandler pTable.DblClick, AddressOf DblClickHandler
      AddHandler pTable.SelectionChange, AddressOf PivotTableSelectionChangedHandler
      

      我承认这一点"让ViewModel处理ActiveX控件"使用对我来说似乎并不好。但这些控制对我们来说是必要的。

2 个答案:

答案 0 :(得分:1)

所以,评论太多了。我相信聚合器没问题。 PRISM可能会为订阅者使用WeakReferences,而VM在发布时使用静态字段来访问EventAggregator(对吗?)。这应该没问题,因为GarbageCollector确实通过引用静态对象来收集实例。

ActiveX控件可能更成问题。你设置了很多房产还是只有几处房产?然后,您可以创建一个包含ActiveX控件的Control。为您需要执行的每个设置定义DependencyProperties,并将它们绑定到viewModel。在DP注册中插入ChangedHandlers。只要在viewModel中设置了一个值,它就会转移到你的控件上,你最终会在属性的changehandler中找到你可以在ActiveX-Control上设置提交值的值(值在EventArgs.NewValue中)。

如果控件的创建不那么简单,转换器才有用。然后在您的XAML中放入ContentPresenter。将内容绑定到Whatever(留空等)并放入一个返回ActiveX控件实例的Converter(IValueConverter)。

希望能帮到你

答案 1 :(得分:1)

我会直接解决这个问题。但是对于长期运行,我认为Gope的解决方案更好,因为它符合MVVM设计。

Gope是对的,问题是因为ActiveX控件持有对我ViewModel的引用(即使ViewModelActiveX控件成员) 。我的问题实际上与此帖Cleaning up WindowsFormsHost in a WPF dialog中的问题相同。我需要调用Dispose()对象的WindowsFormsHost函数来释放主机。我还调用PivotTable.Dispose()来释放ActiveX控件本身(事实上我首先尝试了PivotTable.Dispose()并且PivotTable对象已经发布但主机没有。所以我添加了主机的Dispose功能)。现在,当我使用内存分析器验证时,我的ViewModelPivotTable似乎已正确释放。