我有一个遵循MVVM模式的WPF应用程序。到目前为止,该应用程序定义了两个视图和视图模型:
两个视图模型都需要从其他视图模型中访问几个属性。
示例:LoginViewModel
具有属性ProjectList
ProjectsViewModel
也需要访问此属性。
这只是一个简单的例子。稍后将有几个UserControls
,它们都需要相互交互。
创建一个所有用户控件
(视图)都设置为其 DataContext
的巨大视图模型会更好吗?如果不是,所有不同的视图模型如何相互交互?
备注:< br >这个问题与这个问题密切相关,但方法不同。
你绝对不应该做一个巨大的“主视图模型”——这是一个与上帝对象没有什么不同的反模式。
这里的关键思想是,您的视图模型不需要从其他视图模型访问多个财产;相反,所有视图模型都需要访问特定的信息。
现在,您最有可能在实例化时将这些信息注入到每个视图模型中。与其这样做,不如为每个视图模型提供一个对服务的引用——一个通过属性和/或方法公开这些信息的应用程序模块。如果本质上非常简单,信息可以以标量值的形式公开,如果比标量值更复杂,可以以模型的形式公开。
从示意图上看
/--------------\
| ViewModelA |
| | <=======\
| | |
\--------------/ | <--- information is pulled /================\
+=========[model]===[model]====== | Service |
/--------------\ | \================/
| ViewModelB | |
| | <=======/
| |
\--------------/
服务应该在构造时注入到视图模型中(手动注入,或者通过DI容器注入,如果您正在使用的话)。每个视图模型应该只需要一个对服务的引用和足够的信息来告诉服务它对哪个模型感兴趣;然后,它将向服务请求该模型,并基于该模型填充其“感兴趣的”属性。
这种方式比简单地构造一个viewmodel对象并在外部设置其属性要复杂得多,但是它将允许您的应用程序增加复杂性,而不会变得难以管理。
例如,如果有许多视图绑定在不同的视图模型上,并且这些视图模型以复杂的方式依赖于许多模型,那么一种合理的工作方式是:
如果一切都通过服务路由,这是可能的。想象一下,否则要保持一切同步需要什么——唯一的应对方法是将所有信息放入一个巨大的视图模型中,并从其他一切中引用它。丑陋。
通常我会做以下四件事之一:
>
使我的视图模型相互引用,并传递属性。例如,LoginViewModel
可能会在成功登录时设置 ProjectsViewModel.ProjectList
。如何实现这一点取决于 ViewModel 之间的关联方式,以及逻辑连接点的位置。
创建一个< code > application viewmodel ,用于管理当前页面等内容,以及当前用户或当前项目列表等应用程序范围的对象。它将处理将共享数据传输到需要它的视图模型。
使用某种事件系统在应用程序范围的属性发生变化时广播消息,并让任何感兴趣的视图模型订阅接收这些消息。该消息通常还包含新对象,因此订阅接收该消息类型的任何人都可以访问新对象。(如果你感兴趣的话,我在我的博客文章《视图模型与MVVM之间的交流》中有一个事件系统的简要总结)
根据其他选项是否更好,我可能会考虑创建一个单例来保存应用程序范围的数据。例如,如果用户设置为“登录”,并且从我的许多ViewModel中访问,我可以创建一个单例来将用户设置为首次登录,然后我的所有ViewModel都可以访问它。
我不想做的一件事是创建一个包含所有可用数据的大型ViewModel。ViewModels应仅包含特定于它的数据。
如果您使用某种依赖注入工具,您可以注入一个提供这些值的类,例如,IProjectService,它可以返回每个视图模型上的项目列表。
一个巨大视图模型的想法听起来并不吸引人,视图模型之间通过访问彼此的公共财产而产生的强耦合也不吸引人。如果您希望在视图模型之间进行交互,例如添加项目时,请为您希望发生的每个事件使用发布/订阅模型。