我们当前的应用程序将每个View
包装成一个Window
(这只是一个原型应用程序)。并且每个View
/ Window
都有一个ViewModel
被指定为DataContext。现在我的问题是,当ViewModel
/ Window
关闭时,发布View
的做法是什么?
我尝试处理Window
的Closed事件,并将DataContext设置为NULL。我的ViewModelBase类实现了IDisposable接口。但是当我调试时,我发现没有调用Dispose()函数。当我使用内存分析器时,我发现ViewModel
永远不会被释放。
那么发布ViewModel
更新:
两个潜在的内存泄漏源:
IEventAggregator
来做事件pub / sub。我正在使用Prism 4.1中的EventAggregator
类,但只是将它包装在Singleton类中(它实现了IEventAggregator接口,因为我们还不想使用依赖注入)。在ViewModel
/ View
内,我只是使用(VB.NET中的代码)
_ea.GetEvent(Of MyEventType).Publish(MyEventObject)
_ea.GetEvent(Of MyEventType).Subscribe(AddressOr MyEventHandler)
ViewModel
直接拥有这样的控制成员,我认为这打破了MVVM的规则,这也是我目前只能对代码中的布线ViewModel
进行硬编码的原因 - 在View
。例如,在代码隐藏中,我有这样的行:
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控件"使用对我来说似乎并不好。但这些控制对我们来说是必要的。
答案 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
的引用(即使ViewModel
有ActiveX
控件成员) 。我的问题实际上与此帖Cleaning up WindowsFormsHost in a WPF dialog中的问题相同。我需要调用Dispose()
对象的WindowsFormsHost
函数来释放主机。我还调用PivotTable.Dispose()
来释放ActiveX
控件本身(事实上我首先尝试了PivotTable.Dispose()
并且PivotTable
对象已经发布但主机没有。所以我添加了主机的Dispose功能)。现在,当我使用内存分析器验证时,我的ViewModel
和PivotTable
似乎已正确释放。