多个视图模型之间状态共享的具体示例(WPF MVVM)

33

我有一个使用WPF/Entity Framework(4.0)的项目,其中包含许多对象。我想构建应用程序,以便可以在视图模型之间共享对象选择状态。

例如:我们有Cars、Drivers、Passengers和Cargo类。还有CarList、DriverList等的用户控件和CarEditor、DriverEditor等的编辑器窗口。此外,我们为所有这些都有视图模型(例如CarListViewModel、DriverListViewModel、CargoEditorViewModel等)。这些组成了一个可停靠的界面,在该界面中,用户可以打开多个对象列表、编辑器和查看器。

我想要的是一个具体的代码示例,演示如何将多个视图模型连接起来,以便在CarList中选择一辆汽车会导致该汽车在CarEditorView中实时显示,并在任何其他上下文有效的视图中被选中(例如DriverByCarView-或者只是DriverList如果有过滤谓词)。

根据这个问题,有很多建议和讨论。似乎支配的两种方法是:

  • 3018307:通过提到消息子系统来讨论状态共享
  • 1159035:通过使用封装的视图模型来讨论状态共享

这两种方法中有哪一种更好呢?

是否有任何具体的示例,以编写或创建小代码项目的形式展示这两种方法?

我还在学习WPF,因此欢迎提供阅读API基础知识的入门点,但是我通常会去查看代码示例。

谢谢


如果有人感兴趣,这里还有一些其他类似的讨论:

  • 3816961: 讨论返回多个视图模型取决于对象类型的问题(即符合特定接口的任意类型集合)
  • 1928130: 讨论将视图模型作为其他视图模型的属性聚合是否明智(例如,一个由面板视图模型组成的 MainWindow 视图模型)
  • 1120061: 主要讨论在使用每个模型一个视图模型策略还是每个视图元素使用一个视图模型策略之间的选择。
  • 4244222: 讨论在使用嵌套对象层次结构时是否嵌套视图模型。
  • 4429708: 讨论直接在视图模型之间共享集合的问题,但没有详细说明。
  • List item: 讨论在单个视图模型中管理多个选择的问题。

关于前两篇文章的补充说明:仅当状态共享在模型之间而非视图之间时,消息传递方法才是有效的;而封装的视图模型在另一种情况下是有效的。不确定这是否正确/有效。 - JohnMetta
1个回答

12
一种实现此目的的典型方法是使用一个信使发布一个CarSelected消息,该消息详细说明所选的汽车。零个或多个ViewModel可以订阅CarSelected消息。对当前选择的汽车感兴趣的ViewModel可以监听消息,然后相应地采取行动。
信使方法提供了一个干净的解耦设计,其中发布者和订阅者彼此没有依赖关系,因此可以轻松独立地发展 - 它们只需要知道有关汽车消息的信息。信使是中介者模式的一种实现。
在Prism中,信使是EventAggregator,并用于发布和订阅消息。
更新
除了架构优势外,EventAggregator还实现了弱事件,以防止未明确取消订阅的订阅者的内存泄漏问题。
请参见以下EventAggregator文档:

http://msdn.microsoft.com/en-us/library/ff649187.aspx

棱镜:

http://compositewpf.codeplex.com/

棱镜示例

public class ViewModel1
{
    private readonly IEventAggregator _eventService;
    private Car _selectedCar;

    public ViewModel1(IEventAggregator eventService)
    {
        _eventService = eventService;
    }

    //Databound property...
    public Car SelectedCar
    {
        set
        {
            _selectedCar = value;

            var msg = new CarSelectedMessage { Car = _selectedCar };

            _eventService.GetEvent<CarSelectedEvent>().Publish(msg);
        }
    }
}

public class ViewModel2
{
    public ViewModel2(IEventAggregator eventService)
    {
        eventService.GetEvent<CarSelectedEvent>().Subscribe(msg =>
        {
            //DoStuff with msg...
        });
    }
}

public class Car {}

public class CarMessage
{
    public Car Car { get; set; }
}

public class CarSelectedEvent : CompositePresentationEvent<CarMessage> {}

尽管缺少示例指针,但这确实有所帮助。我一直在考虑观察者模式而不是中介者模式,后者更有意义。我会研究Prism的。谢谢。 - JohnMetta
@JohnMetta 我已经添加了一些Prism的链接。这是我使用的框架,如果你有任何问题,我很乐意帮助。 - Tim Lloyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接