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

本文关键字:通信 建立 之间 数据 viewmodel 两个 | 更新日期: 2023-09-27 18:16:42

我知道这个问题已经被问过很多次了,我也读过很多关于这个问题的答案。然而,他们都没有达到我的要求,因此我需要一些建议。

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

这是一个基于MVVM Light Toolkit的WPF MVVM应用程序。有网格的区域是ListBox + Canvas。这些项目(我们称它们为"neme")同样由每个ListBox + Canvas组成,并由用户动态创建。每个Neume都由"元素"组成,这些元素被渲染成红色的形状。

当用户双击Neume时,将打开一个新窗口。它应该允许编辑(翻译,调整大小,旋转)所选的Neume组成的元素。我想做的是传递我的SelectedNeume(与元素列表)存储在我的MainViewModel到我新创建的窗口的ViewModel。我有一些关于如何实现这一点的想法:

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

我正在寻找一个既简单又整洁的解决方案。我很乐意使用选项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()方法目前负责根据1。选择:

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

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

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

我个人会选择选项3。

消息传递机制使您的视图模型彼此分离,一旦您完成了一个示例,您就会发现这很容易。

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

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;
        }
    }
}

将该属性替换为任何你想要的集合或复杂对象