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

6

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

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

这是一个基于MVVM Light Toolkit的WPF MVVM应用程序。带有网格的区域是一个ListBox+Canvas。项目(我们称之为“诺姆”)又由每个ListBox+Canvas组成,并由用户动态创建。每个Neume由作为红色形状呈现的“元素”组成。

当用户双击一个Neume时,将打开一个新窗口。它应该能够编辑所选Neume所包含的元素(翻译、调整大小、旋转)。我想做的是将存储在我的MainViewModel中的SelectedNeume(具有元素列表)传递给我的新创建的窗口的ViewModel。 我有一些实现这个目标的想法

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

我正在寻找既简单又整洁的解决方案。我很想利用选项3,但是就WPF而言,我是一个相对较新的人,真的不知道如何开始。此外,我担心的是,在触发主ListBox上的双击事件时打开新窗口可能会有问题,因为我无法找到一种方法将命令绑定到ListBoxItem,无论是在其样式还是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() 方法会根据第一种选项绑定 DataContext。
public void SetDataContext()
    {
        if(this.Owner != null)
            DataContext = this.Owner.DataContext;
    }

我的问题是:你会推荐哪一个选项?1或者2有没有什么问题?可能会有内存泄漏吗?

1个回答

7

个人建议选择第三个选项。

消息机制可以使您的视图模型彼此分离,一旦您完成一个示例,您将会发现它非常容易。

个人喜欢添加一个消息代理类,并为每个要发送的消息类型添加静态方法,这有助于我集中更改 - 但实质上,您有一个发送和接收。您可以发送您想要的内容,如果有人想要接收它,他们就可以。

MVVM Light是一个很棒的框架。

发送:

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

在我的目标视图模型构造函数中接收:
this.MessengerInstance.Register<LoginSuccessMessage>(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;
        }
    }
}

将该属性替换为您想要的任何内容,可以是集合或复杂对象。


这就是我所说的跟踪者 :) - kidshaw
跟踪者也可以很友好 ;) - kidshaw
这还能用吗?我在实现时遇到困难。 - Antoine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接