个人随笔
技术改变世界

使用 MVVMLight 消息通知

欢迎阅读我的MVVMLight教程系列文章关于 MVVMLight 设计模式系列

在文章的其实我们就说了,MVVMLight的精华就是消息通知机制,设计的非常不错。这个东西在MVVMLight可以说是用的及其的频繁,当ViewModel请求View要有些改变的时候(比如弹个窗体)那么你在ViewModel里面编写弹窗的代码?那也就违背了MVVM的设计模式啦,MVVMLight的消息通知可以实现互相调用代码而不耦合!

 

MVVMLight_Messenger

如何使用 MVVMLight 消息通知

接着我们上一篇文章的项目,也说过我们这里要修改项目中的不足之处,让代码优雅起来。目前为止我们一共有两个窗体(MainWindowUserView),一个ViewModel(UserViewModel)。我们在使用MainWindow弹出UserView的时候是直接编写的MainWindow中的ButtonClick事件。这样使得MainWindow掌握了业务逻辑,按理什么时候合理的弹出UserView应该是编写ViewModel的人员来决定的。所以我们应该把这个弹出窗口的权利交给ViewModel。

或许至此你会想在ViewModel中编写如下代码?

UserView uv = new UserView();
uv.Show()

但是这样写,对吗?…要是View的编写人员还没有编写出UserView这个类呢?是不是还是没有脱离耦合?还是有这样的依赖性,不是View依赖ViewModel,就是ViewModel依赖View,如何解决?

 

下面我们来看看MVVMLight中的解决办法 – 消息通知

ViewModel是掌握业务逻辑的类,所以我们这里广播一个消息,主意!我这里说的是广播!并不是我要指定这个消息发送给谁

我在 UserViewModel.cs 中使用了如下代码进行了消息广播。

Messenger.Default.Send<object>(null, "ShowUserView");

这个消息发送了个广播,广播的令牌为"ShowUserView",这是个令牌! 跟一个暗语一样,哈哈!只要对的上的就可以收到这个消息,所以我们跟接收者(也就是编写View的工程师)进行约定。到时候接收消息就靠这个令牌了。

这里广播出去的参数是 Object 类型的,由于我什么参数都不需要传递所以我设定了 Send<T> 这个泛型为 object ,参数值为 null (也就是第一个参数)。

 

接收MVVMLight的消息

约定好了一个令牌(这里是“ShowUserView”),我在此注册该令牌,有该令牌的消息时我会收到这个通知,看看我们在View中是如何注册消息并使用的吧!MainWindow.cs 的消息通知部分代码如下!

public MainWindow()
{
    this.DataContext = new MainWindowViewModel();
    InitializeComponent();
    
    //注册MVVMLight消息
    Messenger.Default.Register<object>(this, "ShowUserView", ShowUserView);

    //卸载当前(this)对象注册的所有MVVMLight消息
    this.Unloaded += (sender, e) => Messenger.Default.Unregister(this);
}

//弹出UserView窗体
void ShowUserView(object obj)
{
    new UserView().Show();
}

先看看注册MVVMLight消息的那行代码吧,Register<T> 这里是一个泛型是和我们约定好的一样,我给了object类型,所以我们构建的方法的时候也是要要有一个object类型的参数的方法ShowUserView(object obj)

ok,再继续看看这行代码后面的三个参数。

第一个:this  表示注册该消息的对象,也就是消息接收人的意思,所以我填写当前窗体。

第二个: "ShowUserView" 就是令牌了,跟ViewModel的编写人员约定好的。

第三个:收到消息时要执行的方法,这里我们注册的是  ShowUserView(object obj) 这个方法。

至此,完美! 谁也不依赖谁!什么时候弹出窗体,这些业务逻辑交给ViewModel的编写人员吧。至于弹出什么窗体,窗体多漂亮,窗体怎么设置什么的,这就是编写View的事儿了。

 

似乎还有个没讲…..卸载消息?

有注册肯定有注销咯,如果你不注销的话,这个注册会一直存在。如果你打开了两次MainWinodw则会注册两次。。两个窗体都开着那么收到一条消息的时候就会弹出4个UserView窗体..原因很简单就是因为注册了两次。。。每个窗体就收到两次。。

所以我们在关闭窗体的时候或者你需要停止接收消息的时候来注销消息接受。。。到这里你应该明白 MVVMLight的消息注册机制是一个静态变量在App中全局广播与注册。带来的麻烦确实有,但是有时候也异常的方便。不会存在多个窗体接力传递对象过去使用的情况。

所以我这里在Unloaded事件中对消息进行了注销,下面看看注销的代码

Messenger.Default.Unregister(this);

这个是注销当前对象的所有消息,如果你想注销指定的消息,那么是有重载的,可以指定令牌的名称,如“ShwoUsreView”,敲敲代码试试吧!如下所示!

Messenger.Default.Unregister<object>(this, "ShowUserView");

 

 本文示例源码下载MVVMLightDemo_4

 

至此MVVMLight的消息通知就差不多啦,有疑问或者其他的建议…欢迎在此回复进行讨论!

欢迎阅读我的MVVMLight教程系列文章关于 MVVMLight 设计模式系列》 MVVMLight相关的我会在该目录中进行补充。

转载请注明出处王旭博客 » 使用 MVVMLight 消息通知

分享到:更多 ()

评论 4

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #4

    非常感谢,我还想了解弹出窗口后,用户确认的消息怎么回传呢

    imhzsky2个月前 (03-09)回复
  2. #3

    太谢谢博主了,我要找的就是像这样介绍的教程

    忧蓝5个月前 (11-21)回复
  3. #2

    very good !

    盖伦10个月前 (06-22)回复
  4. #1

    WPF在这里的设计太精妙了 茅塞顿开 谢谢博主

    橙子2年前 (2015-06-26)回复