1

我正在使用 MVVM Light 框架以及 Unity for DI。我有一些嵌套视图,每个都绑定到相应的 ViewModel。ViewModel 通过 Laurent Bugnion 放入 MVVM Light 的 ViewModelLocator 想法绑定到每个 View 的根控件 DataContext。这允许通过静态资源查找 ViewModel,并通过依赖注入框架(在本例中为 Unity)控制 ViewModel 的生命周期。它还允许 Expression Blend 查看与 ViewModel 相关的所有内容以及如何绑定它们。

正如我所说的,视图有一个健康的嵌套剂量,但视图模型并不真正了解彼此。父视图通过静态资源 ViewModelLocator 绑定到其对应的 ViewModel(它使用 Unity 来控制 ViewModel 对象的构造和生命周期)。该父视图包含一个用户控件,它是另一个子视图,然后它也会通过 ViewModelLocator 获取其对应的 ViewModel。ViewModel 之间没有相互引用,也不知道彼此之间的任何层次结构。

因此,这里有一个 ViewModel 如何通过消息传递进行交互的示例。我有一个父视图,它有一个 ComboBox 数据绑定到其 ViewModel 中的 ObservableCollection。ComboBox 的 SelectedItem 也绑定(双向)到 ViewModel 上的一个属性。当 ComboBox 的选择发生变化时,这是为了触发其他 View 和子 View 中的更新。目前,我正在通过 MVVM Light 中的消息系统来完成此操作。

所以我想知道从一个 ViewModel 到另一个 ViewModel 获取信息的最佳做法是什么?在这种情况下,我需要传递给子 ViewModels 的基本上是代表当前登录用户的用户 Guid。最顶层的父视图(好吧,ViewModel)会知道这些信息,但我不确定如何将它放到子视图模型中。

我能想到的一些可能的方法:

  • 子 ViewModel 是否应该向静态资源 ViewModelLocator 请求对父 View 正在使用的同一对象的引用并以这种方式访问​​该属性?似乎 ViewModel 遍历彼此的属性不是很干净,并且不必要地将它们耦合在一起。

  • 我已经在使用消息来通知子视图用户在 ComboBox 中选择了一个新项目并进行相应更新。但在 ComboBox 中选择的对象类型与子视图所需的数据值并没有真正直接的关系。

4

2 回答 2

3

我基本上已经看到了两种方法。对于一般的跨 VM 通信,事件聚合器模式效果很好。

然而,对于 VM 的层次结构,使用访问者模式可能会更好。通过访问者,您可以获得流经层次结构的信息,例如自动为每个孩子提供对父 VM 的引用。

您也可以使用 EA 执行此操作,但挑战在于在消息的有效负载中传递足够的信息,以便孩子们知道这是他们应该关心的事情。

至于VM定位器,绝对不是!VM 定位器的内容严格用于在 UI 中绑定,它不应该在该上下文之外出现(最好)。

我的 0.02 美元格伦

于 2010-03-31T06:02:53.410 回答
0

我决定让子 ViewModel 发布一条请求所需信息的消息,然后让父 VM 订阅该消息类型和密钥令牌。我不想过度使用这种通信方式,但我认为它对于一些我无法找到通过 View 层次结构向下推的方法的数据将是有效的。到目前为止,大部分数据传递都是为了响应事件,但并不是每条数据都可以通过这种方式传递,尤其是在获取数据或事件发生在新视图之前的不同屏幕上时甚至被构造和读取以接收数据。

我确实与这个领域的一些知名人士(Glenn Block、John Papa 和 Rob Eisenberg)在 Twitter 上进行了对话。他们提出了许多类似访问者模式的建议,但我不确定如果没有 VM 的层次结构,它是否能很好地工作。这可能是因为我的设计几乎是 View-first,而不是 ViewModel-first 方法。另一个可能可行的建议是修改我的 ViewModelLocator 和依赖注入使用,以包括在创建时将数据值传递给子 VM 的能力。由于 VML 的静态特性,我在设想它时遇到了一点困难,并决定我提出的消息请求解决方案暂时更直接和简单。

于 2010-04-02T02:47:07.003 回答