如何在两个ViewModel之间建立通信/传递数据 [英] How to establish communication/pass data between two ViewModels

查看:1333
本文介绍了如何在两个ViewModel之间建立通信/传递数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经被问过无数次了,并且我已经阅读了很多有关此问题的答案.但是,它们都不满足我的要求,因此我需要一些建议.

I'm aware this question has already been asked numerous times, and I've read many answers referring to it. Nevertheless, none of them fulfilled my requirements, and hence I need some advice.

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

The application I'm developing at the current moment looks like this: http://screenshooter.net/100101493/smrkpog

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

It's a WPF MVVM application based on MVVM Light Toolkit. The area with a grid is a ListBox + Canvas. The items (let's call them 'Neumes') consist again of a ListBox + Canvas each and are dynamically created by a user. Every Neume is composed of 'Elements' which are rendered as the red shapes.

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

When the user double-clicks a Neume, a new window opens. It is supposed to enable editing (translate, resize, rotate) of the Elements the selected Neume is made of. What I'd like to do is to pass my SelectedNeume (with a list of Elements) stored in my MainViewModel to the ViewModel of my newly created window. I have a few ideas on how to achieve this:

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

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

I'm looking for a solution that is both simple and neat. I'd be most happy to make use of option 3., but I'm a relative newbie as far as WPF is concerned, and don't know how to start really. Also, I'm afraid there might be a problem with the fact that the new window is opened when a double-click event on the main ListBox is fired, since I couldn't find a way to bind a command to the ListBoxItem neither in its Style nor DataTemplate (the event trigger/EventToCommand solution didn't work for me).

这是事件:

    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:

The SetDataContext() method currently takes care of binding the DataContext according to the 1. option:

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

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

My question is: Which option would you recommend? Are there any problems with either 1. or 2.? Possible memory leaks?

推荐答案

我个人会选择选项3.

消息传递机制使视图模型彼此分离,一旦完成一个示例,您会发现它很简单.

The messaging mechanism keeps your viewmodels separated from each other and once you work through one example, you'll see it is quite easy.

我个人想为要发送的每种消息类型添加一个带有静态方法的消息代理类,这有助于我集中更改-但从本质上讲,您已经可以发送和接收消息了.您可以发送您想要的东西,如果有想要接收的东西,他们可以.

Personally I like to add a message broker class with static methods for each message type I want to send, this helps me centralise changes - but essentially you've got a send and receive. You can send what you want and if something wants to receive it they can.

MVVM Light是一个很好的框架.

MVVM Light is a great framework for this.

发送:

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

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

Receive, in my target View Model constructor:

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

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

Handler in the target View Model:

    private async void OnLoginSuccessMessage(LoginSuccessMessage message)
    {
        this.CurrentUserName = message.UserName;
        this.MoveToState(ApplicationViewModelState.Active);

        await Task.Delay(5000);
        this.MoveToState(ApplicationViewModelState.Idle);
    }

在此示例中,我将用户ID作为消息类的属性发送:

In this example, I am sending a user ID as a property on the message class:

public class LoginSuccessMessage : MessageBase
{

    private string _UserName;

    public string UserName
    {
        get
        {
            return this._UserName;
        }

        set
        {
            this._UserName = value;
        }
    }
}

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

Replace that property with whatever you want be that a collection or complex object.

这篇关于如何在两个ViewModel之间建立通信/传递数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆