简体   繁体   English

MVVMLight Messenger有范围吗?

[英]Does the MVVMLight messenger have scope?

Imagine a WPF application with one main view representing a window that can be opened multiple times. 想象一个WPF应用程序,其中一个主视图代表一个可以多次打开的窗口。 This main view has several child views. 该主视图有几个子视图。

The messenger could send messages between the viewmodels of the main view and its child views' viewmodels. Messenger可以在主视图的视图模型与其子视图的视图模型之间发送消息。

Can the messenger be made to have a restricted scope so that if you had two main views open, interacting with one would message only that view's child views? 可以使Messenger的范围受到限制,以便在打开两个主视图时与之交互只向该视图的子视图发送消息吗?

Is there another way to share an "identity" between the parent and child view models in a way that honours MVVM? 是否有另一种方式可以以尊重MVVM的方式在父视图模型和子视图模型之间共享“身份”?

You could use the concept of "tokens" to achieve this effect. 您可以使用“令牌”的概念来实现此效果。

The IMessenger interface has overloads of Register and Send that accept an object to restrict which registrants receive a message. IMessenger接口的RegisterSend重载接受对象,以限制哪些注册者接收消息。 If a message is sent with a token, the only objects that will see the message are those that registered for the message with the same token. 如果使用令牌发送消息,则唯一会看到该消息的对象是使用相同令牌为消息注册的对象。 Here, "same" means object equality, so you can use any object for the token that has sensible equality semantics and makes sense to you, ie a GUID, integer, or string. 在这里,“相同”表示对象相等,因此您可以将具有合理的相等语义且对您有意义的任何对象用于令牌,即GUID,整数或字符串。

As an example, consider the following objects: 例如,请考虑以下对象:

public static class MessengerHelper
{
    public static IMessenger Messenger { get { return GalaSoft.MvvmLight.Messaging.Messenger.Default; } }
    public static object Group1Token { get { return 1; } }
    public static object Group2Token { get { return 2; } }
}

public class FooChild
{
    object token;

    public FooChild(object token)
    {
        this.token = token;
        MessengerHelper.Messenger.Register<IFooMessage>(this, token, HandleFooMessage);
    }

    void HandleFooMessage(IFooMessage fooMessage)
    {
        Console.WriteLine("FooChild got the message, token = " + (token ?? "(null)"));
    }
}

public class FooParent
{
    FooChild[] children;

    public FooParent()
    {
        children = new [] { 
            new FooChild(MessengerHelper.Group1Token),
            new FooChild(MessengerHelper.Group2Token),
            new FooChild(null)
        };
    }

    public void SendFooMessage(IFooMessage fooMessage, object token)
    {
        MessengerHelper.Messenger.Send(fooMessage, token);
    }
}

Then if you create the parent and send a message with the given tokens: 然后,如果您创建父级并发送带有给定令牌的消息:

FooParent parent = new FooParent();
parent.SendFooMessage(new FooMessage(), MessengerHelper.Group1Token);
parent.SendFooMessage(new FooMessage(), MessengerHelper.Group2Token);

You'll get the following output: 您将获得以下输出:

FooChild got the message, token = 1 FooChild收到消息,令牌= 1

FooChild got the message, token = 2 FooChild收到消息,令牌= 2

In your case, you'll want each main view models to have their own token, and pass their token to their child view models. 对于您的情况,您将希望每个主视图模型都有自己的令牌,并将其令牌传递给子视图模型。

You can always choose between passing default IMessenger which will have static , application domain scope or creating new instance of messenger: 您始终可以在传递默认的IMessenger (具有静态 ,应用程序域范围)或创建Messenger的新实例之间进行选择:

var domainWideMessenger = GalaSoft.MvvmLight.Messaging.Messenger.Default;
var localMessenger = new Messenger();

First approach is useful when you don't want to control scope of messenger. 当您不想控制Messenger的范围时,第一种方法很有用。 You can treat it as a central hub. 您可以将其视为中央枢纽。 "local" messengers are good for communications within VM or within some container. “本地”信使非常适合在VM或某些容器内进行通信。

Why this might be better then having tokens?! 为什么这比拥有令牌更好? When you have advanced application with messaging built on tokens at some point you'll face difficulties handling them (picking the right one). 当您拥有基于令牌的消息传递的高级应用程序时,您将在处理它们时遇到困难(选择正确的令牌)。 Especially when it comes to dependency injection. 特别是在涉及依赖注入时。

In your case you'll have new instance of Messenger per MainView which will be pushed down to all its child views and view models. 在您的情况下,每个MainView将具有Messenger新实例,该实例将被下推到其所有子视图和视图模型。 To sync data and communicate between multiple instances of MainView use static Messenger from MVVM Light. 要在MainView多个实例之间同步数据并进行通信,请使用MVVM Light中的静态Messenger

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM