我正在构建一个基于MVVM-Light的应用程序。我需要创建同一个View的多个实例,每个实例都应绑定到自己的ViewModel。
默认ViewModelLocator
将ViewModels实现为单例,因此同一View的不同实例将绑定到同一ViewModel。
我可以在VMLocator中创建ViewModel作为非静态对象(就像返回新的VM()...一样简单),但这只会对我有所帮助。 事实上,我仍然需要跟踪打开的窗口。然而,每个窗口可能会打开其他几个窗口(不同类型)。在这种情况下,我可能需要在父View及其所有子项上执行一些操作。例如,在关闭View P之前,我可能想要关闭它的所有子节点(视图C1,视图C2等)。
因此,有没有简单易行的方法来实现这一目标?或者您有什么建议我遵循的最佳做法?
提前感谢您的宝贵帮助。
干杯,
詹卢卡。
答案 0 :(得分:11)
没有义务将ViewModel存储为ViewModelLocator中的单例,但如果视图也是单例,它肯定会更容易找到。显然,如果您有同一View类的多个实例,那么您将拥有同一ViewModel类的多个实例,并且它不再是单例。
要跟踪ViewModel的多个实例,您可以在ViewModelLocator中实现一个字典,该字典根据键查找ViewModel。例如,密钥可以是视图的唯一ID。获取视图后,检索其密钥,然后从定位器中检索viewmodel。
更新:通常您甚至不需要跟踪多个视图模型。例如,您可以让Messenger类使用Send重载向给定viewmodel类的所有实例发送消息。因此,在实现字典以跟踪VM之前,请问自己是否真的需要它! ;)
希望有所帮助, 劳伦
答案 1 :(得分:0)
我使用了统一容器的命名系统。
请参阅“How to distinguish multiple view/view model pairs using unity container”。
答案 2 :(得分:0)
我在 this SO question 中发布并解决了问题。事实证明这与Bugnion先生的答案非常相关(这对我帮助很大,谢谢!)
我发现你根本不需要在ViewModelLocator中存储view-model属性。只需使用ServiceLocator
创建一个带密钥的实例,然后在“对话服务”中将密钥传递给ShowDialog<T>(string key = null)
。
此外,正如此主题中已提到的那样,请使用方法Messenger.Default.Send
并记住之后调用viewModel.Cleanup()
以从Messenger
取消注册视图模型,从而防止虚幻视图模型尝试处理发送到视图模型类类型的所有实例的未来消息。