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

标签 c# wpf xaml mvvm mvvm-light

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

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

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

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

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

我正在寻找一种既简单又巧妙的解决方案。我很乐意使用选项 3.,但就 WPF 而言,我是一个相对的新手,不知道如何真正开始。此外,我担心当主 ListBox 上的双击事件被触发时新窗口打开可能存在问题,因为我找不到将命令绑定(bind)到 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. 选项绑定(bind) DataContext:

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

我的问题是:您会推荐哪个选项? 1. 或 2. 有任何问题吗?可能的内存泄漏?

最佳答案

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

消息传递机制使您的 View 模型彼此分离,一旦您完成一个示例,您就会发现它非常简单。

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

MVVM Light 是一个很好的框架。

发送:

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

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

this.MessengerInstance.Register<LoginSuccessMessage>(this, this.OnLoginSuccessMessage);

目标 View 模型中的处理程序:

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

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

关于c# - 如何在两个 ViewModel 之间建立通信/传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25158972/

相关文章:

c# - Javascript block 内的 ASP MVC Razor foreach

c# - 如何使用 Microsoft.Build.Evaluation.Project.RemoveItem

wpf - WPF中带字幕的边框

wpf - telerik 忙指示器不可见

c# - 内部 StackPanel 不可见

c# - 在一个exe中包含另一个exe

c# - 带有 SSL 和 ASP.NET 的 ERR_CONNECTION_RESET

c# - 如何隐藏文本框、标签和按钮 C# WPF

c# - 如何设置值如果组合框不更改 WPF MVVM 模式中的值

c# - WPF: 'ListView.ItemsSource' 属性在 'Loaded' 事件期间为空