何时在MVVM Light中丢弃ViewModel

5
我正在研究如何开始使用MVVM Light,并遇到了“新”的ICleanup接口。我想知道什么时候清理VM...当您从页面导航离开时吗?
此外,我看到ViewModelLocator中有一个Main Cleanup,它应该清理所有的VM...什么时候会使用它?
非常感谢。
敬礼, Mauro
1个回答

8
ICleanup接口相对于之前的IDispose实现的优点在于,可以更频繁地调用它而不标记VM为已释放。这意味着你应该在需要注销VM的消息处理时调用ICleanup.Cleanup。当然,在这种情况下,你需要有一个方法,在以后需要时重新注册所有消息处理程序。
个人而言,我更喜欢使用IDispose处理VM清理的方式,特别是因为我倾向于使用IOC容器。但是,我能够看到Laurent的观点,并且在VM上实现IDisposable并调用Cleanup并不是什么特技。
一般来说,何时释放/清理VM取决于它如何被实例化和对象的声明周期。这些决策由你的应用程序设计管理,并且没有明确的指导说明应该在何时进行。但是请记住,每当在您的ViewModel中注册了消息处理程序时,都必须进行清理/释放 - 在其他情况下,这不是绝对必要的。
在谈论消息处理程序时,不要忘记在视图中也取消注册它们(请参见此帖子)。-仔细想想,我会将代码放在这里,以便清楚地了解和供以后参考:
在你视图的代码后台文件的构造函数中添加以下代码,以确保在视图卸载时释放已注册的消息处理程序:
public MyView() {
    this.Unloaded += (o, e) => { Messenger.Unregister(this); }
}

谢谢回复。我现在更好地理解了清理信使后面整个概念。 - Mauro
我认为 Messenger 使用 WeakReference 的原因是不需要注销,而且注销的原因不仅仅是为了清理。 - Ralph Shillington
2
@RalphShillington:它应该做到,但它没有。这是一个已知的问题。在注册处理程序时,引起引用保持的是函数,尽管它不应该这样。原因是对于匿名和静态函数,弱引用无法正常工作。Laurent、其他人和我都研究过这个问题,最好的建议是...注销! - AxelEckenberger
只是发现使用Unloaded处理这种场景存在问题。在我看来,如果我的视图托管在TabItem中并且用户切换到另一个TabItem,则会触发该TabItem的Unloaded事件。 - 000
是的,这可能会成为一个问题。然而,这也取决于您的应用程序设计。通常情况下,一旦不再需要视图实例,我就不会保留它。如果您需要保留窗口,则可以考虑替代的初始化策略,例如在窗口显示之前调用的方法。 - AxelEckenberger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接