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

时间:2011-01-05 00:22:15

标签: c# wpf mvvm data-binding

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

例如:我们有汽车,司机,乘客和货物类。我们还有CarList,DriverList等的UserControls以及CarEditor,DriverEditor等的编辑器窗口。此外,我们有所有这些的视图模型(CarListViewModel,Dri​​verListViewModel,CargoEditorViewModel等)。这一切都构成了一个可停靠的界面,用户可以在其中打开多个对象列表,编辑器和查看器。

我想要的是如何连接多个视图模型的具体代码示例,以便在CarList中选择汽车将使该汽车在CarEditorView中生效,但也可以在上下文有效的任何其他视图中选择(例如DriverByCarView-或者只有DriverList,如果有过滤谓词)。

基于这个问题,有许多建议和讨论。似乎占主导地位的两种方法是:

  • 3018307:通过提及消息传递子系统来讨论状态共享
  • 1159035:使用封闭的viewmodel
  • 讨论状态共享

其中一种方法比其他方法更好吗?

是否有人以书面或小型代码项目的形式有这两种方法的具体例子?

我还在学习WPF,所以我们非常感谢阅读API基础知识的入门点,但是查看代码示例是我经常去的地方。

由于


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

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

1 个答案:

答案 0 :(得分: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> {}