编程语言
首页 > 编程语言> > c# – 具有相同ViewModel的多个实例的MVVM-Light Messenger

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