15

我有一个遵循 MVVM 模式的 WPF 应用程序。到目前为止,该应用程序定义了两个视图和视图模型:

  • 登录视图(模型)
  • 项目视图(模型)

两个视图模型都需要访问其他视图模型的多个属性。

示例:
LoginViewModel有一个属性ProjectListProjectsViewModel也需要访问此属性。

这只是一个简单的例子。稍后将有几个UserControls都需要相互交互。

UserControls创建一个所有(视图)都设置为它们的巨大视图模型会更好DataContext吗?如果不是,那么所有不同的视图模型如何相互交互?

备注:这个问题与这个
问题密切相关,但方法不同。

4

5 回答 5

50

你绝对不应该制作一个巨大的“主视图模型”——这是一个与上帝对象没有什么不同的反模式。

这里的关键思想是您的视图模型不需要访问其他视图模型的多个属性;相反,所有视图模型都需要访问特定的信息

现在,您很可能在实例化时将此信息注入每个视图模型。不要这样做,而是为每个视图模型提供对服务的引用——通过属性和/或方法公开此信息的应用程序模块。如果信息本质上非常简单,则可以以标量值的形式公开,如果比这更复杂,则可以以模型的形式公开。

从示意图上看,这看起来像

/--------------\
|  ViewModelA  |
|              | <=======\
|              |         |
\--------------/         |  <--- information is pulled      /================\
                         +=========[model]===[model]======  |    Service     |
/--------------\         |                                  \================/
|  ViewModelB  |         |
|              | <=======/
|              |
\--------------/

该服务应在构造时注入视图模型(手动或通过 DI 容器,如果您正在使用)。每个视图模型应该只需要对服务的引用和足够的信息来告诉服务它对哪个模型感兴趣;然后它将从服务中请求该模型并基于此填充其“有趣”属性。

这种做事方式比简单地构建视图模型对象并在外部设置其属性更复杂,但它会让您的应用程序变得复杂而不会变得难以管理。

例如,如果有很多视图绑定在不同的视图模型上,并且这些视图模型以复杂的方式依赖于许多模型,那么一种理智的工作方式是:

  1. 构造了一个视图/视图模型对
  2. viewmodel 从服务请求它需要知道的任何模型;它订阅服务公开的事件以让订阅者知道模型已更改
  3. 通过数据绑定控件对模型执行更改
  4. 视图调用视图模型上的“保存”命令
  5. 作为响应,视图模型在服务上调用“保存此模型”方法
  6. 服务持久化信息并发布“模型更改”事件(参见步骤 2)
  7. 对同一模型感兴趣的其他视图模型知道模型已更改,并且可以查询服务以获取其新状态

如果一切都通过服务路由,这是可能的。想象一下保持一切同步需要什么 - 应对的唯一方法是将所有信息放入一个巨大的视图模型中并从其他所有内容中引用它。丑陋的。

于 2013-01-16T15:26:51.083 回答
5

Usually I do one of 4 things:

  • Make my ViewModels reference each other, and pass the property around. For example, LoginViewModel might set ProjectsViewModel.ProjectList on successful login. How you implement this depends on how your ViewModels are related to each other, and where logical points of connection would be.

  • Make an ApplicationViewModel which manages things like which page is current, and application-wide objects like the current user or current project list. It would handle transferring shared data to the ViewModels that needs it.

  • Use some kind of Event system to broadcast a message anytime an application-wide property changes, and have any ViewModel that's interested subscribe to receive those messages. The message typically contains the new object as well, so anyone subscribed to receive that message type has access to the new object. (I have a brief summary of Event Systems in my blog article Communication between ViewModels with MVVM if you're interested)

  • Depending on if any of the other options work better, I may consider creating a singleton to hold application-wide data instead. For example, if the User is set on Login and is accessed from many of my ViewModels, I may create a singleton to set the user on first login, and then all my ViewModels can access it.

The one thing I would not do is make one big ViewModel holding all available data. ViewModels should only contain the data specific to it.

于 2013-01-16T15:32:38.767 回答
1

您的模型应该包含项目列表之类的内容,或者让您能够访问它。ViewModel 只是作为模型和视图之间的一个层,让您有机会将不同的模型对象组合在一起并将它们塑造成视图可以轻松显示的形状并处理来自视图的命令(修改模型以响应)。

于 2013-01-16T15:28:31.160 回答
1

如果您使用某种依赖注入工具,您可以注入一个提供这些值的类,例如 IProjectService,它可以返回每个视图模型上的项目列表。

一个巨大的视图模型的想法听起来并不吸引人,视图模型之间通过访问彼此的公共属性的强耦合也没有。如果您想要视图模型之间的交互,例如添加项目时,请为您希望发生的每个事件使用发布/订阅模型。

于 2013-01-16T15:24:05.150 回答
1

创建一个基本视图模型,其中保留所有常见属性,为 BaseViewModel 创建单例并将该单例属性添加到所有视图模型中。所有 Viewmodel 将一次同步。

于 2017-03-01T09:19:50.737 回答