MVVM中视图模型的交互

Rob*_*uch 14 wpf properties mvvm viewmodel

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

  • LoginView(型号)
  • ProjectsView(型号)

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

示例:
LoginViewModel有一个属性ProjectList.ProjectsViewModel也需要访问此属性.

这只是一个简单的例子.之后会有几个UserControls都需要互相交流.

创建一个所有UserControls(视图)设置为他们的巨大视图模型会更好DataContext吗?如果没有,所有不同的视图模型如何相互作用?

备注:
这个问题是密切相关的这一个,但有不同的方法.

Jon*_*Jon 44

你绝对不应该制作一个巨大的"主视图模型" - 这是一种与上帝对象不同的反模式.

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

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

示意性地看起来像

/--------------\
|  ViewModelA  |
|              | <=======\
|              |         |
\--------------/         |  <--- information is pulled      /================\
                         +=========[model]===[model]======  |    Service     |
/--------------\         |                                  \================/
|  ViewModelB  |         |
|              | <=======/
|              |
\--------------/
Run Code Online (Sandbox Code Playgroud)

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

这种做事方式比简单地构建一个viewmodel对象并在外部设置其属性更为复杂,但它将允许您的应用程序在复杂性上增长而不会变得难以管理.

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

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

如果所有内容都通过服务路由,则可以执行此操作.想象一下如何保持所有内容同步 - 唯一的方法就是将所有信息放入一个巨大的视图模型中并从其他所有内容中引用它.丑陋.

  • @RobertStrauch - 这就是程序员的生活. (3认同)

Rac*_*hel 5

通常我会做以下四件事之一:

  • 让我的 ViewModel 相互引用,并传递属性。例如,LoginViewModel可能ProjectsViewModel.ProjectList在成功登录时设置。您如何实现这一点取决于您的 ViewModel 如何相互关联,以及连接的逻辑点在哪里。

  • 创建一个ApplicationViewModel管理诸如当前页面之类的内容,以及当前用户或当前项目列表等应用程序范围的对象。它将处理将共享数据传输到需要它的 ViewModel。

  • 使用某种事件系统在应用程序范围的属性更改时广播消息,并让任何感兴趣的 ViewModel 订阅接收这些消息。消息通常也包含新对象,因此订阅接收该消息类型的任何人都可以访问新对象。(如果您有兴趣,我在我的博客文章“ ViewModels 与 MVVM 之间的通信”中对事件系统进行了简要总结)

  • 根据是否有任何其他选项效果更好,我可能会考虑创建一个单例来保存应用程序范围的数据。例如,如果用户在登录时设置并从我的许多 ViewModel 访问,我可能会创建一个单例来在第一次登录时设置用户,然后我的所有 ViewModel 都可以访问它。

不会做的一件事是制作一个包含所有可用数据的大 ViewModel。ViewModels 应该只包含特定于它的数据。