c# – 具有相同ViewModel的多个实例的MVVM-Light Messenger
作者:互联网
我在MVVM上相对较新,并遇到了一个问题.我们正在使用MVVM-Light框架在WPF中编写数据库应用程序.程序状态的规范我们必须能够立即打开ClaimView的多个实例.
要打开新窗口,我们将从ViewModel发送一条消息,该消息将在View中捕获,并打开新窗口.我们使用枚举令牌来识别正确的收件人以获取请求.
现在,如果我有两个ClaimView实例同时打开,并且我调用Messanger,它会打开两个相同的窗口,因为两个视图都在接收消息.
我们尝试在单独的线程上运行ViewModel的每个实例,并通过输出ManagedThreadId进行验证,并且两个实例仍然收到消息.
我们也注册了注册消息,因此这不是问题.
任何帮助,将不胜感激.
解决方法:
新答案
正如OP(Daryl)所指出的那样,我的原始答案(见下文)并不完全正确,所以我提供了一个新的答案,以防有同样问题的人稍后遇到这个问题:
有意义的是,如果您有两个实例注册具有相同令牌的相同消息类型,则两个实例都将接收该消息.解决方案是提供每个View-ViewModel对唯一的令牌.
您可以将枚举值放在类中,而不是仅使用普通枚举值作为标记,如下所示:
public class UniqueToken
{
public MessengerToken Token { get; private set; }
public UniqueToken(MessengerToken token)
{
Token = token;
}
}
然后在ViewModel中添加一个新属性来存储其中一个唯一标记:
// add a property to your ViewModel
public UniqueToken OpenWindowToken { get; private set; }
// place this in the constructor of your ViewModel
OpenWindowToken = new UniqueToken(MessengerToken.OpenWindow);
// in the appropriate method, send the message
Messenger.Send(message, OpenWindowToken);
最后,在View中,您现在可以获取唯一令牌并使用它来注册OpenWindow消息:
var viewModel = (MyViewModel)DataContext;
var token = viewModel.OpenWindowToken;
Messenger.Register<TMessage>(this, token, message => OpenWindow(message));
ViewModel和View都必须使用UniqueToken的单个实例,因为如果接收者令牌和发件人令牌是完全相同的对象,则messenger将仅发送消息,而不仅仅是具有相同属性值的实例.
原始答案(不完全正确)
我想你的问题可能有一个拼写错误:你说要打开一个新窗口,你会从ViewModel向View发送一条消息,但后来你说两个ViewModel都在接收消息.你的意思是两个视图都收到消息?
在任何情况下,有意义的是,如果您有两个实例注册具有相同令牌的相同消息类型,则两个实例都将接收该消息.
要解决此问题,您首先需要ViewModel的每个实例都具有唯一ID.这可以通过Guid实现.就像是:
// add a property to your ViewModel
public Guid Id { get; private set; }
// place this in the constructor of your ViewModel
Id = Guid.NewGuid();
然后你需要你的令牌成为一个具有两个属性的对象:一个用于guid,一个用于枚举值:
public class UniqueToken
{
public Guid Id { get; private set; }
public MessengerToken Token { get; private set; }
public UniqueToken(Guid id, MessengerToken token)
{
Id = id;
Token = token;
}
}
然后,当您在View中注册(或者它是您的ViewModel?)时,您需要从ViewModel中获取Guid.这可能是这样的:
var viewModel = (MyViewModel)DataContext;
var id = viewModel.Id;
var token = new UniqueToken(id, MessengerToken.OpenWindow);
Messenger.Register<TMessage>(this, token, message => OpenWindow(message));
最后,在ViewModel中,您需要执行以下操作:
var token = new UniqueToken(Id, MessengerToken.OpenWindow);
Messenger.Send(message, token);
编辑
输入完所有内容之后,我发现你并不真正需要ViewModel上的Id属性.您可以使用ViewModel本身作为唯一标识符.因此,对于UniqueToken,您可以使用公共MyViewModel ViewModel替换公共Guid Id,它应该仍然有用.
标签:c,mvvm,wpf,mvvm-light 来源: https://codeday.me/bug/20190612/1228016.html