2010-03-28 67 views
1

我正在使用MVVM Light框架以及Unity for DI。我有一些嵌套的视图,每个绑定到相应的ViewModel。 ViewModel通过Laurent Bugnion放入MVVM Light的ViewModelLocator想法绑定到每个View的根控件DataContext。这允许通过静态资源查找ViewModel并通过依赖注入框架来控制ViewModel的生命周期,在这种情况下Unity。它还允许Expression Blend查看有关ViewModel的所有内容以及如何绑定它们。传递或从父ViewModel获取值到Sub-ViewModel?

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

因此,下面是ViewModel如何通过消息传递进行交互的示例。我有一个父视图,它有一个ComboBox数据绑定到其ViewModel中的ObservableCollection。 ComboBox的SelectedItem也绑定(双向)到ViewModel上的一个属性。当组合框的选择更改时,这将触发其他视图和子视图中的更新。目前我正通过MVVM Light中的消息系统完成此任务。

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

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

  • 如果子视图模型问 静态资源ViewModelLocator为 到 父视图使用同一个对象的引用,并访问 属性,办法?看起来像 ViewModels经历对方的 属性不是很干净, 不必要地将它们连接在一起。

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

+0

实际上,经过身份验证的用户标识不是我需要从顶级ViewModel获得的唯一值; DatePicker控件中还有一个开始日期和结束日期值,需要传递给子ViewModels以过滤一些数据。 – mkmurray 2010-03-30 05:22:07

回答

0

我决定子的ViewModels发布请求所需的信息的消息,然后让母VM订阅的消息类型和密钥令牌。我不想过度使用这种通信手段,但我认为这对于少数数据有效,而我无法通过查看层次结构下推数据。到目前为止,大部分数据传递都是响应事件,但并不是每个数据都能以这种方式传递,尤其是在新视图之前获取数据或事件发生在不同屏幕上的情况下甚至被构造并阅读以接收数据。

我确实与这个空间中的一些知名人物(Glenn Block,John Papa和Rob Eisenberg)进行了推特对话。他们提出了许多类似访问者模式的内容,但我不确定如果没有虚拟机层次结构,这样做会很好。这可能是因为我的设计几乎是View-first,而不是ViewModel优先的方法。另一个可行的建议是修改ViewModelLocator和Dependency Injection的使用,以便在创建时将数据值传递给子虚拟机。由于VML的静态特性,我设想它有点麻烦,并决定我提出的消息请求解决方案将会更简单直接。如果最终会有太多数据落入这种情况,我可能不得不重新考虑解决方案。

3

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

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

您也可以使用EA做到这一点,但挑战在于在消息的有效载荷中传递足够的信息,以便孩子知道他们应该关心的事情。

就VM定位器而言,绝对不是!虚拟机定位器的东西严格的绑定在用户界面中,它不应该将其自身置于该上下文之外(最佳)。

我的$ .02 格伦

+0

一般的好的答案和它的一部分接近我选择的解决方案。尽管我没有虚拟机层次结构,但只有视图是嵌套的,然后恭维虚拟机是绑定到每个视图的数据。我想我最终得到了像EA这样的东西;我会发布一个解释我做了什么的答案。 – mkmurray 2010-04-02 02:32:04