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

时间:2014-08-06 11:17:50

标签: c# wpf xaml mvvm mvvm-light

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

我目前正在开发的应用程序如下所示: http://screenshooter.net/100101493/smrkpog

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

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

  1. 完全跳过新的ViewModel并将MainViewModel设置为新窗口的DataContext
  2. 在新的ViewModel中创建一个'MainViewModel'字段,并在打开一个新窗口时将其传递给那里,
  3. 使用MVVM Light Toolkit提供的Messaging / Mediator模式。
  4. 我正在寻找既简单又整洁的解决方案。我很乐意使用选项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.是否有任何问题?可能的内存泄漏?

1 个答案:

答案 0 :(得分:7)

就个人而言,我会选择3。

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

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

MVVM Light是一个很好的框架。

发送:

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

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

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

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

相关问题