新答案
正如 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);
最后,在您的视图中,您现在可以获取唯一令牌并使用它来注册 OpenWindow 消息:
var viewModel = (MyViewModel)DataContext;
var token = viewModel.OpenWindowToken;
Messenger.Register<TMessage>(this, token, message => OpenWindow(message));
ViewModel 和 View 都必须使用 UniqueToken 的单个实例,因为只有当接收者令牌和发送者令牌是完全相同的对象时,信使才会发送消息,而不仅仅是具有相同属性值的实例。
原始答案(不太正确)
我认为您的问题可能有一个错字:您说要打开一个新窗口,您会从 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;
}
}
然后当你在你的视图中注册时(或者它是你的视图模型?),你需要从视图模型中获取 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);
编辑
输入所有内容后,我突然想到您实际上并不需要Id
ViewModel 上的属性。您可以只使用 ViewModel 本身作为唯一标识符。因此,对于UniqueToken
,您可以只替换public Guid Id
为public MyViewModel ViewModel
,它应该仍然可以工作。