如何在两个MVVM对之间进行通信?

时间:2013-08-06 20:00:52

标签: c# wpf mvvm architecture

我有一个小应用程序,概述了一些项目(条目)。概述列表中条目的标题是条目的属性。 当我单击一个条目时,应该打开一种选项卡,我可以在其中编辑条目。编辑并保存条目时,概览选项卡应在下次更新时更新。

Here一个更好理解的模型。

App基于MVVM模式。每个View都有一个ViewModel作为DataContext。每个ViewModel使用模型每个模型都有一个数据库
概览选项卡具有自己的View,ViewModel和Model(对)。标签。条目的每个选项卡使用相同的对(单例实例)。只更新几个绑定如果选择了其他选项卡。

我的问题是如何在标签之间进行通信。

我有两种方法

  • 介体模式(Bootstrapper将两个ViewModel与介体组合在一起)
  • 每个模型使用相同的数据库(模型监听数据库,ViewModel听模型)

但我对这些方法并不满意 我应该在模型之间还是在ViewModel之间进行通信?或者这是错误的方式?

更新

我非常感谢你的所有答案。在我看来,没有一个是错的或正确的。我认为这是一个品味问题,解决方案适合一个人。我非常喜欢EventAggregator模式。 HereKarl Shifflett关于EventAggregator patternPRISM实施情况的精彩视频。但它也解释了模式本身。

@Thomas在我看来,在一个ViewModel中执行此操作是一个糟糕的解决方案。 ViewModels必须分开。 MVVM基于Separation of Concerns

4 个答案:

答案 0 :(得分:2)

Mediator是朝着正确方向迈出的一步,但Event Aggregator更灵活。你可以找到十几个实现。例如,Prism有一个随时可用的实现。

ViewModels之间的沟通。 ViewModels在Aggregator中注册自己的通知,并在聚合器上发出通知。

答案 1 :(得分:2)

如果功能与格式化模型数据相关,则应在ViewModel之间进行通信。如果您正在将数据从一个模型传递到另一个模型,则在模型之间进行通信

下面是一个具体示例:Microsoft.Practices.Prism命名空间,您可以在Visual Studio中使用NuGet访问,包含一个名为CompositePresentationEvent<T>的类,以及一个EventAggregator类来完成实际沟通。

整个应用程序的常见位置(我选择了App.xaml.vb,但它可以是任何公共范围的代码文件,它也适用于C#和VB),您可以通过继承该类来定义事件,并且提供与您发送的数据相对应的类型T.例如,如果要发送包含简单字符串的消息,请声明:

Public Class MyEvent: Inherits CompositePresentationEvent(Of String) : End Class

在Application类中,您定义了一个事件聚合器:

Public Shared ReadOnly AppEventAggregator As IEventAggregator = New EventAggregator()

这两个项目共同为您提供了在应用程序中任意两个对象之间交换事件的方法。

这使您的整个应用程序可以访问名为MyEvent的事件。无论您要将MyEvent消息发送到何处,都可以调用其共享的Publish(String)方法:

Application.AppEventAggregator.GetEvent(Of MyEvent).Publish("This is my event message")

然后,要接收事件,您需要在事件应该着陆的类中实现一个私有的只读字段,如:

Private ReadOnly MyEventToken As SubscriptionToken =
Application.AppEventAggregator.GetEvent(Of MyEvent).Subscribe(Sub(eventMessage) DoSomethingWithTheString(EventMessage))

... DoSomethingWithTheString(eventMessage As String)将是您处理活动的地方。

当然,Prism还有很多(但很多),但从来没有需要使用超过你需要的东西,正如其他人所指出的那样,许多其他MVVM框架都有类似的方法来解决同样的问题。

答案 2 :(得分:2)

对我来说,当我必须为视图模型之间的通信编程时,这通常是一个不好的迹象。有时,您必须在视图和视图模型之间进行通信,但是如果可能,连接两个视图模型的需要似乎总是会导致组合两个视图模型。

凭借你的模型,我感受到了同样的不良情绪。为什么首先要为标签设置单独的视图模型?在您的情况下,视图可以是独立的,但我没有看到分离视图模型的任何好处。因此,将两种视图模型合二为一是我的建议。

答案 3 :(得分:1)

也许this帖子对你很有意思,它描述了基于类型的通信模式。它允许您在所需的一切之间进行通信,而不会相互依赖