【问题标题】:Concrete examples of state sharing between multiple viewmodels (WPF MVVM)多个视图模型之间状态共享的具体示例(WPF MVVM)
【发布时间】:2011-06-03 17:49:58
【问题描述】:

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

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

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

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

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

其中一种方法是否比另一种更好?

有没有人以书面或小代码项目的形式提供这两种方法中的一种/两种方法的具体示例?

我仍在学习 WPF,因此可以提供指向阅读 API 基础知识的入口点的指针,但我通常会查看代码示例。

谢谢


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

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

【问题讨论】:

  • 作为关于前两篇链接文章的附录:只有当状态共享在模型之间而不是视图之间时,消息传递方法才有效;而封闭的视图模型在另一种情况下有效。不确定这是否正确/有效。

标签: c# wpf mvvm data-binding


【解决方案1】:

实现此目的的典型方法是使用信使发布 CarSelected 消息,详细说明所选汽车。零个或多个 ViewModel 可以订阅 CarSelected 消息。对当前选择的汽车感兴趣的 ViewModel 可以监听该消息,然后采取相应的行动。

messenger 方法提供了一种清晰的解耦设计,其中发布者和订阅者之间没有依赖关系,因此可以轻松地独立发展 - 他们只需要了解汽车消息即可。 Messenger 是中介者模式的一种实现。

在 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> {}

【讨论】:

  • 尽管没有指向示例的指针,但这确实有帮助。我在考虑观察者模式而不是调解者,这更有意义。我会研究棱镜。谢谢。
  • @JohnMetta 我为 Prism 添加了几个链接。这是我使用的框架,所以如果您有任何问题,很乐意提供帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-14
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 2014-10-11
  • 2012-01-15
  • 1970-01-01
相关资源
最近更新 更多