从父ViewModel传递或获取值到Sub-ViewModel?

时间:2010-03-28 21:24:05

标签: xaml mvvm nested viewmodel mvvm-light

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

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

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

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

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

  • 子ViewModel是否应该询问 静态资源ViewModelLocator for 对同一个对象的引用 父View正在使用和访问 财产那样?这好像是 ViewModels经历彼此的 属性不是很干净 不必要地将他们聚在一起。

  • 我已经在使用短信通知了 用户选择的子视图 ComboBox中的一个新项目 相应更新。但是对象 正在选择的类型 ComboBox并不是直接的 与此数据值相关的那个 子视图需要。

2 个答案:

答案 0 :(得分:3)

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

对于VM的层次结构,但使用访问者模式可能更好。对于访问者,您可以获得流经层次结构的信息,例如为每个子项自动引用父VM。

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

至于VM定位器,绝对不行! VM定位器的内容非常严格地用于UI中的绑定,它不应该在该上下文之外(最佳地)表现出来。

我的$ .02 格伦

答案 1 :(得分:0)

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

我确实与这个领域的一些知名人士进行过Twitter谈话(Glenn Block,John Papa和Rob Eisenberg)。他们建议了一些像访问者模式这样的东西,但是如果没有虚拟机层次结构,我不确定它会如何运作。这可能是因为我的设计几乎是View-first,而不是ViewModel-first方法。另一个可行的建议是修改我的ViewModelLocator和Dependency Injection使用,以包括在创建时将数据值传递给子VM的能力。由于VML的静态特性,我设想它有点麻烦,并且我认为我提出的消息请求解决方案暂时更直接和简单。如果最终有太多的数据落入这种情况,我可能不得不重新考虑解决方案。