View Model之间的WPF MVVM通信

我正在研究WPF MVVM应用程序,其中我有两个视图View1和View2及其各自的ViewModel。 现在,我希望单击View1中的按钮将关闭View1并使用ViewModel1打开View2。 此外,我想从ViewModel1打开时向ViewModel2传递一些人类实例,该实例将用于在View2中显示信息。

在ViewModels中实现这一目标的最佳方式和最简单方法是什么,我希望避免在代码后面编写导航代码。

如何使用Mediator模式(例如参见technical-recipes.com或John Smith )或弱事件? Afaik的几个MVVM框架/库(如PRISM,Caliburn.Micro,MVVMCross)已经为这些提供了基础设施代码。 还有独立于任何特定mvvm框架的独立库,如Appccelerate EventBroker ,它可以帮助您实现您想要的某些内容。

但是,对于事件,我想知道您是否需要一些反馈是否“正确”处理了事件。 有办法实现这一点(改变事件args的值,处理事件同步,提升事件,检查事件args的值),但它们不像方法的返回值或抛出exception的方法那样简洁。

编辑:抱歉,我刚刚意识到第二个视图/ viewmodel尚未打开。 所以我的“解决方案”不适用(简单地说)。 您需要在视图模型树中“up”传递指令,甚至可以传递给根,您可以在其中实例化并显示新的视图模型(在新窗口中显示或在现有视图中显示为ContentControl?)

我创建了这个Messenger类来处理ViewModels之间的通信。

MainViewModel注册添加的人物对象:

 Messenger.Default.Register(this, AddPersonToCollection, Context.Added); 

要从CreatePersonViewModel通知所有已注册的ViewModel有关添加的人员:

 Messenger.Default.Send(person, Context.Added); 

源代码:

 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace Application.Messaging { public class Messenger { private static readonly object CreationLock = new object(); private static readonly ConcurrentDictionary Dictionary = new ConcurrentDictionary(); #region Default property private static Messenger _instance; ///  /// Gets the single instance of the Messenger. ///  public static Messenger Default { get { if (_instance == null) { lock (CreationLock) { if (_instance == null) { _instance = new Messenger(); } } } return _instance; } } #endregion ///  /// Initializes a new instance of the Messenger class. ///  private Messenger() { } ///  /// Registers a recipient for a type of message T. The action parameter will be executed /// when a corresponding message is sent. ///  ///  ///  ///  public void Register(object recipient, Action action) { Register(recipient, action, null); } ///  /// Registers a recipient for a type of message T and a matching context. The action parameter will be executed /// when a corresponding message is sent. ///  ///  ///  ///  ///  public void Register(object recipient, Action action, object context) { var key = new MessengerKey(recipient, context); Dictionary.TryAdd(key, action); } ///  /// Unregisters a messenger recipient completely. After this method is executed, the recipient will /// no longer receive any messages. ///  ///  public void Unregister(object recipient) { Unregister(recipient, null); } ///  /// Unregisters a messenger recipient with a matching context completely. After this method is executed, the recipient will /// no longer receive any messages. ///  ///  ///  public void Unregister(object recipient, object context) { object action; var key = new MessengerKey(recipient, context); Dictionary.TryRemove(key, out action); } ///  /// Sends a message to registered recipients. The message will reach all recipients that are /// registered for this message type. ///  ///  ///  public void Send(T message) { Send(message, null); } ///  /// Sends a message to registered recipients. The message will reach all recipients that are /// registered for this message type and matching context. ///  ///  ///  ///  public void Send(T message, object context) { IEnumerable> result; if (context == null) { // Get all recipients where the context is null. result = from r in Dictionary where r.Key.Context == null select r; } else { // Get all recipients where the context is matching. result = from r in Dictionary where r.Key.Context != null && r.Key.Context.Equals(context) select r; } foreach (var action in result.Select(x => x.Value).OfType>()) { // Send the message to all recipients. action(message); } } protected class MessengerKey { public object Recipient { get; private set; } public object Context { get; private set; } ///  /// Initializes a new instance of the MessengerKey class. ///  ///  ///  public MessengerKey(object recipient, object context) { Recipient = recipient; Context = context; } ///  /// Determines whether the specified MessengerKey is equal to the current MessengerKey. ///  ///  ///  protected bool Equals(MessengerKey other) { return Equals(Recipient, other.Recipient) && Equals(Context, other.Context); } ///  /// Determines whether the specified MessengerKey is equal to the current MessengerKey. ///  ///  ///  public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((MessengerKey)obj); } ///  /// Serves as a hash function for a particular type. ///  ///  public override int GetHashCode() { unchecked { return ((Recipient != null ? Recipient.GetHashCode() : 0) * 397) ^ (Context != null ? Context.GetHashCode() : 0); } } } } } 

使用微小的专用Light Message Bus 。 它不是任何MVVM框架的一部分,因此可以独立使用它。 非常容易安装和使用。

使用指南