MVVM Light Messenger多次执行问题

7

我正在使用MVVM Light,并使用消息在ViewModel之间进行通信,以让一个ViewModel知道何时可以执行某些操作。我的问题是,我注册了一条消息,然后它会多次接收到它。为了防止程序执行多次操作,我必须创建布尔标志来查看它是否已经被接收过了。您有什么想法,为什么会这样,并且如何停止它?


你的消息发送到哪里了?你是否已经逐步查看了MVVM Light源代码,以找出为什么消息会被多次发送的原因?在回答你的问题之前,有一定的工作量或更多的细节需要提供。 - Matt Casto
5个回答

9
请确保在不再需要它们时取消注册您的消息处理程序。Messenger 会保留已注册方法的引用,这会阻止它们被垃圾回收。
因此,对于 ViewModel:确保在完成后调用 Cleanup(或实现 IDisposable 并从其中调用 Cleanup)。
对于视图(控件、窗口或类似物),请在视图拆除时触发的事件中调用 Messenger.Unregister,例如 Unloaded 事件。
这是 MVVM 的已知行为,并已在多个地方进行了讨论。

1
在WPF中,UserControl.Unloaded事件不像http://connect.microsoft.com/VisualStudio/feedback/details/575287/the-usercontrol-unloaded-event-is-not-raised-when-the-mainwindow-gets-closed所述的那样保证被触发,因此这并不容易。 - Ian Kemp
我想说的是,你必须在 Messenger 后面进行清理,否则它会继续处理消息,尽管它不应该这样做了。Unloaded 事件是一个地方,但可能不是唯一或最好的地方。 - AxelEckenberger
取消注册示例代码 - Messenger.Default.Unregister<NotificationMessage<TemplateSelectedForActionPayLoad>> ( this, NotificationReceivedWithTemplateSelection ); - BUDDHIKA
更简单的方式:Messenger.Default.Unregister(this) - 取消注册与 this 相关联的所有消息。 - AxelEckenberger

7

这是一个很老的问题,但我通过以下方法解决了它:

static bool isRegistered = false;

然后,在构造函数中:

if( !isRegistered )
{
   Messenger.Default.Register<MyMessage>(this, OnMessageReceived);
   isRegisterd = true;
}

这很可能是解决问题的方法,不要在构造函数中注册 Messenger。 - Jay Kannan
虽然这可以防止重复注册,但并不能确保消息被正确的实例处理。也不能保证一个实例不会因为注册而一直存在。 - AxelEckenberger

1
我之前见过这个问题。这与 Messenger.Default.Register 被多次调用有关。MVVMLight Messenger 类将注册相同的项“x”次数。这就是为什么当你调用 Send 时会得到多个结果。
有没有人知道如何防止 MVVMLight 多次注册?

我发现我的问题至少是因为其他视图模型和视图仍然在内存中挂起。我仍然有一个问题,需要从vm发送消息到视图。我的问题现在是,所有先前的此视图实例仍然在内存中,因此消息会被发送和接收多次。 - Jason

1

虽然我很老了,但我还是想回答一下,以防有人需要。当时我对Silverlight还比较陌生,问题最终被确定为内存泄漏,因为ViewModel仍然在内存中存在多个实例。


0

正如其他贡献者所提到的,同一条消息被注册了多次。我注意到这种行为发生在导航到视图X然后返回到视图Z时,在Z ViewModel的构造函数中注册了该消息。一个解决方案是将NavigationCacheMode属性设置为Required

<Page
  ........
  ........
  NavigationCacheMode="Required">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接