ViewModel事件注册和ViewModel生命周期

问题描述:

我有一个架构问题,以及我想要一个意见的可能解决方案。我习惯了WP7的MVVM体系结构(只要有可能,但不幸的是,有时sdk似乎走向相反的方向)。ViewModel事件注册和ViewModel生命周期

WP7强制使用ViewFirst方法,我觉得这很适合(除了我们无法重写视图创建的部分,就像在Silverlight中,使构造函数注入成为可能)。 我发现自己很有信心,因为大部分视图模型都遵循其视图的lyfetime。所以viewmodel是在创建视图时创建的(通过访问ViewModelLocator),ViewModel是(或者应该)只能被其视图引用,当视图被销毁时,它的ViewModel也应该被销毁(它不是强制性的,而是它的方式我去除非常罕见的情况下,我创建一个singleton viewmodel)。

我的viewmodel可能需要注册一些单例服务事件(我创建的phoneservice或singleton类)。我的意思是,它可能需要注册一个类,该类的生命周期不是由视图模型本身决定的。 这些事件对我的viewmodel保持了一个硬引用,并且即使视图被删除,我的viewmodel也仍然存在,不仅如此,我的viewmodel将继续接收和处理这些事件。 WeakEvent模式可能是一种可能的解决方案,但对于为每个事件创建事件管理器都是不可取的。在我看来,最好的解决方案并不存在,并且应该成为弱事件注册的关键词。

我找到的解决方案是让我的viewmodel知道NavigateTo和NavigateFrom,所以我可以从那里注册和取消注册事件。我还可以添加一些逻辑(例如,我只能在注销的情况下取消注册),注意在NavigateTo和NavigateFrom中有高光逻辑。

另一种可能的方式(我还没有测试过)可能会让我的viewmodel意识到视图定型并在视图完成时执行一些清理,但我总是有这种感觉,因为这种方法并不被推荐使用,定稿。此外,我不清楚性能会受到多大影响。

您如何看待viewmodel生命周期与其视图相同(它总是简化我的应用程序直到现在)? 您如何看待NavigateTo-Navigate从ViewModel感知解决方案? 您对View-Finalization ViewModel感知解决方案有什么看法? 您是否遇到过这些或其他类型的解决方案?

问候 SkyG

UPDATE

我发现,最终确定的解决方案不会做的工作怎么一回事,因为它可以发生在未来的后期(也许永远不会)。 现在看来我认为最好的解决方案是viewmodelbase中的一对虚拟方法,用于初始化和清理视图应该调用的事件注册注销。 可能会调用它们的时刻可能是在加载和卸载事件期间(当我不需要我的viewmodel处理事件时,如果我处于后续视图中,在这种情况下,第一个视图/ viewmodel仍然在后台存活但如果它们的视图被连接/分离到可视化树上,则会加载/卸载)。

任何其他意见(甚至confermative)将不胜感激。

谢谢

,你有什么看法具有视图模型的寿命是一样的 视图(它总是简化我的应用程序到现在为止)?

这对我来说听起来很合理,因为它与视图的DataContext直接相关。

您如何看待NavigateTo-Navigate从ViewModel知道 解决方案?

我不认为这是一个好主意。在MVVM模式中,ViewModels应该对视图一无所知。导航通常与观点相关,所以我不认为这是最好的主意。

您如何看待定型ViewModel感知解决方案 ?

没有具体谈论定稿,视图模型的清理方法是IMO的路要走。在您所有的ViewModels的基类(我希望你有一个),你可以把下面的方法:

public abstract class ViewModelBase 
{ 
    .... 
    public virtual void Cleanup(); 
} 

然后,只需拨打myViewModel.CleanUp();当你的视图被关闭。 取消注册事件的具体实施CleanUp

public override void CleanUp() 
{ 
    ....Event -= this....EventHandler; 
} 
+0

我同意ViewModel不应该是viewaware,但我打算它不应该是特定的viewaware。我可以让ViewModel知道导航而不知道视图(例如使用Messenger)。有没有其他技术上的原因,你不喜欢这种方法?对于清理它听起来不错,唯一的问题是什么时候调用它,并且我只能想到在导航过程中调用它仍然与上面相同或在定稿期间,你有任何其他想法? – SkyG 2012-02-09 17:38:03

+0

我也发现定稿不会奏效,因为它可能会在未来发生。视图模型库中的虚拟清理是最好的解决方案(所以视图只会了解基础)。我必须弄清楚什么时候是最好的时机。在大多数情况下,Unloaded事件可能是唯一的(记住,视图从视觉树中分离的所有时间都被称为视图,但视图可以在后台堆栈中继续存在)。在这种情况下,事件注册应该在加载的事件中发生,所以我需要添加一个Initialize方法到viewmodel基础。 – SkyG 2012-02-10 12:35:45

我同意弱事件的想法是好的,但它会太麻烦来实现。它也创造了它自己的问题 - 它可以使viewmodel完全弱引用,使它在实际“应该”之前成为垃圾收集方式的候选者(开发者意见vs垃圾回收者意见)。之前我已经被Ward Bell咬过了,这个blog post of his

根据您的要求和渴望遵循MVVM的“纯粹”方法(viewmodel不知道视图),似乎您正在努力平衡“视图”和“模型”之间的平衡视图模型。在这种情况下,我实际上会提出另一种设计模式:MVPVM(model/view/presenter/viewmodel)。这里有一个MSDN article

就你而言,主持人将坚持这些单身事件。主持人了解视图是可以的,因为主持人并不意味着在视图之间重复使用。然后,您的视图模型将成为“视图模型”,允许重复使用并消除大多数生命周期问题。

我喜欢MVPVM方法,因为当我的视图模型开始承担太多责任时,它始终关注我MVVM(与数据访问层交谈,监听应用程序范围内的事件以及处理来自视图的命令,维护其视图的属性等)。我知道这不一定是你的问题的答案,但对于评论太长了。