想象一个WPF应用程序,其中一个主视图表示可以多次打开的窗口。此主视图具有多个子视图。
信使可以在主视图的视图模型和其子视图之间发送消息。的ViewModels。
是否可以使信使具有受限制的范围,以便如果您打开两个主要视图,与其中一个视图进行交互只会发出该视图的子视图?
是否有另一种方式来分享"身份"以尊重MVVM的方式在父视图模型和子视图模型之间进行?
答案 0 :(得分:1)
您可以使用"令牌"达到这个效果。
IMessenger
接口具有Register
和Send
的重载,它们接受一个对象来限制哪些注册人收到消息。如果使用令牌发送消息,则将看到该消息的唯一对象是为具有相同令牌的消息注册的对象。在这里,"相同"表示对象相等,因此您可以将任何对象用于具有合理的相等语义且对您有意义的令牌,即GUID,整数或字符串。
例如,请考虑以下对象:
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);
}
}
然后,如果您创建父级并发送带有给定标记的消息:
FooParent parent = new FooParent();
parent.SendFooMessage(new FooMessage(), MessengerHelper.Group1Token);
parent.SendFooMessage(new FooMessage(), MessengerHelper.Group2Token);
您将获得以下输出:
FooChild得到了消息,令牌= 1
FooChild得到了消息,令牌= 2
在您的情况下,您希望每个主视图模型都有自己的令牌,并将其令牌传递给子视图模型。
答案 1 :(得分:1)
您始终可以选择传递默认IMessenger
,它将具有静态,应用程序域范围或创建信使的新实例:
var domainWideMessenger = GalaSoft.MvvmLight.Messaging.Messenger.Default;
var localMessenger = new Messenger();
当您不想控制Messenger的范围时,第一种方法很有用。您可以将其视为中心枢纽。 “本地”信使有利于VM内或某些容器内的通信。
为什么这可能比使用令牌更好?!如果您在某些时候使用基于令牌的消息传递进行高级应用程序,那么处理它们时会遇到困难(选择正确的应用程序)。特别是在依赖注入时。
在您的情况下,您将获得Messenger
每个MainView
的新实例,该实例将被下推到其所有子视图和视图模型。要同步数据并在MainView
的多个实例之间进行通信,请使用MVVM Light中的静态Messenger
。