如何在两个ViewModel之间建立通信/传递数据

我知道这个问题已经被多次询问了,我已经阅读了很多关于它的答案。 然而,它们都没有满足我的要求,因此我需要一些建议。

我正在开发的应用程序看起来像这样: http : //screenshooter.net/100101493/smrkpog

它是基于MVVM Light Toolkit的WPF MVVM应用程序。 带网格的区域是ListBox + Canvas 。 这些项目(让我们称之为“Neumes”)再次由ListBox + Canvas组成,并由用户动态创建。 每个Neume都由’Elements’组成,它们呈现为红色形状。

当用户双击Neume时,将打开一个新窗口。 它应该允许编辑(翻译,resize,旋转)所选Neume的元素。 我想要做的是将存储在MainViewModel中的SelectedNeume(带有一个Elements列表)传递给我新创建的窗口的ViewModel。 我对如何实现这个有一些想法

  1. 完全跳过新的ViewModel并将MainViewModel设置为新窗口的DataContext
  2. 在新的ViewModel中创建一个’MainViewModel’字段,并在打开一个新窗口时将其传递给那里
  3. 使用MVVM Light Toolkit提供的Messaging / Mediator模式。

我正在寻找既简单又整洁的解决方案。 我很乐意使用选项3.但就WPF而言,我是一个相对新手,并且不知道如何真正开始。 此外,我担心当主ListBox上的双击事件被触发时,新窗口打开的事实可能会出现问题,因为我找不到将命令绑定到ListBoxItem的方法。它的Style还是DataTemplate(事件触发器/ EventToCommand解决方案对我不起作用)。

这是事件:

  private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var item = ((FrameworkElement)e.OriginalSource).DataContext as Neume; if (item != null) { var view2 = new EditWindow(); view2.Owner = this; view2.SetDataContext(); view2.ShowDialog(); } } 

SetDataContext()方法当前负责根据1.选项绑定DataContext:

 public void SetDataContext() { if(this.Owner != null) DataContext = this.Owner.DataContext; } 

我的问题是 :你会推荐哪种方案? 1.或2.是否有任何问题? 可能的内存泄漏?

我个人会选择3。

消息传递机制使您的视图模型彼此分离,一旦您完成一个示例,您将看到它非常简单。

就个人而言,我喜欢为我想发送的每种消息类型添加一个带有静态方法的消息代理类,这有助于我集中更改 – 但实际上你有一个发送和接收。 你可以发送你想要的东西,如果想要收到它,他们可以。

MVVM Light是一个很好的框架。

发送:

 GalaSoft.MvvmLight.Messaging.Messenger.Send(new LoginSuccessMessage() { UserName = user }); 

在我的目标View Model构造函数中接收:

 this.MessengerInstance.Register(this, this.OnLoginSuccessMessage); 

目标视图模型中的处理程序:

  private async void OnLoginSuccessMessage(LoginSuccessMessage message) { this.CurrentUserName = message.UserName; this.MoveToState(ApplicationViewModelState.Active); await Task.Delay(5000); this.MoveToState(ApplicationViewModelState.Idle); } 

在这个例子中,我发送一个用户ID作为消息类的属性:

 public class LoginSuccessMessage : MessageBase { private string _UserName; public string UserName { get { return this._UserName; } set { this._UserName = value; } } } 

将该属性替换为您想要的集合或复杂对象。