C# MvvmLight消息传递-注册和注销消息的正确方式是什么?

C# MvvmLight消息传递-注册和注销消息的正确方式是什么?,c#,mvvm,uwp,mvvm-light,C#,Mvvm,Uwp,Mvvm Light,我遇到了一个问题,消息会多次触发,因为当消息在视图的构造函数中注册时,它会被注册多次。大部分S.O.帖子、网站、博客都有这样的例子: public ConstructorOfView() { DataContext = viewModelObject; Messenger.Default.Register<SomeClass>(recipient, token, method); } public someUnloadOrNavigateFromMethod() {

我遇到了一个问题,消息会多次触发,因为当消息在视图的构造函数中注册时,它会被注册多次。大部分S.O.帖子、网站、博客都有这样的例子:

public ConstructorOfView() {
    DataContext = viewModelObject;
    Messenger.Default.Register<SomeClass>(recipient, token, method);
}

public someUnloadOrNavigateFromMethod() {
    Messenger.Default.Unregister<SomeClass>(parameters and more);
}
公共构造函数视图(){
DataContext=viewModelObject;
Messenger.Default.Register(收件人、令牌、方法);
}
public SomeUnloaderAvigateFromMethod(){
Messenger.Default.Unregister(参数等);
}
注销似乎对我没有影响。一些示例说明在ViewModel中注册消息。这对我来说没有意义,原因有两个:1)如果将页面的DataContext设置为ViewModel,ViewModel构造函数会像view构造函数一样再次被调用两次。2) 如果您在ViewModel中注册了一条消息,除了将其公开为静态外,您如何确切地告诉视图启动一个显示消息对话框的方法?。在viewmodel中调用与UI相关的元素(如对话框)的第三个选项似乎违反了MvvM的概念

注册和注销邮件的正确方式是什么


有些帖子建议使用viewmodel调用Cleanup(),但不知何故,您需要将邮件注册到viewmodel,但我不清楚如果将邮件的收件人设置为viewmodel,viewmodel如何在视图中调用非公共静态方法来更改/显示UI?

我通常使用一种模式,其中我的视图模型在IOC容器中注册(查看MVVMLight starter应用程序中的VireModelLocator类)并在viewmodel构造函数中注册消息

这样,由于ViewModel的创建是由IOC处理的,因此相关视图的多个创建不会有问题,消息注册只发生一次

还请记住,注册和取消注册消息将很容易让您进入一个非常难以找到bug的世界,在那里您发送消息,但由于某些原因,没有处理程序注册

我还要补充一点,99%的视图/视图模型交互应该通过绑定进行


我强烈建议查看MvvmLight提供的WPF应用程序模板,以便识别和理解编程模式。

感谢您的回复。有一件事我很困惑。如果在viewmodel中注册消息,当对话框应该在视图中而不是在viewmodel中处理时,如何更改或显示类似对话框的UI?这就是在viewmodel中注册消息对我来说没有意义的地方。我理解你的怀疑,并不知何故同意。事实上,有很多解决方案,也基于您编写代码的平台。如果您正在为Windows编写wpf应用程序,第一个可能是:不要成为mvvm极端主义者,直接调用MessageBox.Show在您的消息处理程序中显示。我有时会这样做,它是有效的,它违反了一些MVVM原则,但可能会为您节省数百行代码。第二:重新考虑如何向用户显示消息,并使用绑定到某些UI控件来显示消息。第三:显示新的弹出视图,而不是对话框。