我可以告诉你,我已经经历了 100% 的痛苦。我想我们是内存泄漏兄弟。
不幸的是,我在这里想到的唯一事情与您的想法非常相似。
我们所做的是创建一个附加属性,视图可以将其应用于自身以将处理程序绑定到 ViewModel:
<UserControl ...
common:LifecycleManagement.CloseHandler="{Binding CloseAction}">
...
</UserControl>
那么我们的 ViewModel 就只有一个 Action 类型的方法:
public MyVM : ViewModel
{
public Action CloseAction
{
get { return CloseActionInternal; }
}
private void CloseActionInternal()
{
//TODO: stop timers, cleanup, etc;
}
}
当我的 close 方法触发时(我们有几种方法可以做到这一点......它是一个 TabControl UI,在选项卡标题上带有“X”,诸如此类),我只是检查这个视图是否已经注册了自己与 AttachedProperty。如果是这样,我调用那里引用的方法。
这是一种非常迂回的方法,只是检查 View 的 DataContext 是否为 IDisposable,但当时感觉更好。检查 DataContext 的问题是您可能有也需要此控件的子视图模型。您要么必须确保您的视图模型链转发此 dispose 调用,要么检查图表中的所有视图并查看它们的数据上下文是否是 IDisposable(呃)。
我觉得这里少了点什么。还有一些其他框架试图以其他方式缓解这种情况。你可以看看Caliburn。它有一个处理这个问题的系统,其中 ViewModel 知道所有子视图模型,这使它能够自动向前链接事物。特别是,有一个名为 ISupportCustomShutdown 的接口(我认为这就是它的名称)有助于缓解此问题。
然而,我做过的最好的事情是确保并使用良好的内存泄漏工具,例如 Redgate Memory Profiler,它可以帮助您可视化对象图并找到根对象。如果您能够确定 DispatchTimer 问题,我想您已经在这样做了。
编辑:我忘记了一件重要的事情。 DelegateCommand 中的一个事件处理程序可能导致内存泄漏。这是 Codeplex 上关于它的一个线程,它解释了它。 http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4065
最新版本的 Prism (v2.1) 已修复此问题。 (http://www.microsoft.com/downloads/details.aspx?FamilyID=387c7a59-b217-4318-ad1b-cbc2ea453f40&displaylang=en)。