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

如何使用 MVVMLight 消息通知
接着我们上一篇文章的项目,也说过我们这里要修改项目中的不足之处,让代码优雅起来。目前为止我们一共有两个窗体(MainWindow、UserView),一个ViewModel(UserViewModel)。我们在使用MainWindow弹出UserView的时候是直接编写的MainWindow中的Button的Click事件。这样使得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 消息通知
使用 MVVMLight 消息通知的更多相关文章
- MVVMLight消息通知实现机制详解(二)
接上文 MVVMLight消息通知实现机制详解(一) 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型.Key值.Action.Target(订阅对象本身) 在发生订阅事 ...
- MVVMLight消息通知实现机制详解(一)
最近对委托.事件的订阅使用的太多,订阅与被订阅之间的绑定约束非常...麻烦,所以翻了下MVVMLight源码找出这段可以拿出来用的部分,详情见下: 一.开发中遇到的问题: 场景1:ClassA中存在事 ...
- UWP消息通知
在Windows 10通常是使用Toast通知方式进行的消息通知,但是在应用通知是不需要通知带有音效的,但是又不能在系统通知中心留下记录,那么需要监听ToastNotification实例的Dismi ...
- Redis系列二之事务及消息通知
一.事务 Redis中的事务是一组命令的集合.一个事务中的命令要么都执行,要么都不执行. 1.事务简介 事务的原理是先将一个事务的命令发送给Redis,然后再让Redis依次执行这些命令.下面看一个示 ...
- Redis笔记(六)Redis的消息通知
Redis的消息通知可以使用List类型的LPUSH和RPOP(左进右出),当然更方便的是直接使用Redis的Pub/Sub(发布/订阅)模式. >>使用List实现队列 使用列表类型的L ...
- 使用 Windows10 自定义交互消息通知
消息通知是最常用的应用功能之一了,但是由于平台的差异,IOS Android 以及 Windows 都有其特殊性,Android开发者在国内常常都是使用三方的一些推送服务,或者是使用自建的服务器为应用 ...
- Android中的消息通知(NotificationManager和Notification)
下面来谈谈notification,这个notification一般用在电话,短 信,邮件,闹钟铃声,在手机的状态栏上就会出现一个小图标,提示用户处理这个通知,这时手从上方滑动状态栏就可以展开并处理这 ...
- Android消息通知(notification)和PendingIntent传值
通知栏的自定义布局:转:http://blog.csdn.net/vipzjyno1/article/details/25248021 拓展 实现自定义的通知栏效果: 这里要用到RemoteViews ...
- cordova的android notify消息通知插件
最近在学习用CORDOVA(PHONEGAP)结合SENCHA TOUCH开发应用,想实现一个安卓下的消息通知功能,这个可以通过CORDOVA的插件来实现. 插件目录结构如下: notifyplugi ...
随机推荐
- Oracle PLSQL Demo - 14.定义定参数的显示游标
declare v_empno scott.emp.empno%type; v_sal scott.emp.sal%type; ) is select t.empno, t.sal from scot ...
- [转]SQL Server 2012 的 T-SQL 新功能 – 新的数据分析函数(LEAD、LAG)
当您需要在 SQL Server 中利用 T-SQL 比较结果集的每一列跟前一列或后一列的差异时,在过去可能需要利用 CURSOR 搭配临时表变量,或是透过递归 CTE 来达到这个效果,如今 SQL ...
- c#的static什么时候使用
C# 什么时候用static? 2011-10-14 14:37江户川奈叶 | 浏览 1733 次 Perl 在static void Main()的方法外面设一个 static int amoun ...
- POj 1753--Flip Game(位运算+BFS)
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30669 Accepted: 13345 Descr ...
- 【JS】通过JS实现超市小票打印功能——ActiveX控件
应客户的需求= = ,要在网页端实现打印小票的功能 先来一张打印出的小票效果图(合计明显不对,因为有修改订单功能,请各位忽略) 用什么方法实现呢: 我想应该是有三种吧 1.用第三方的浏览器控件(这个好 ...
- CKFinder 弹出窗口操作并设置回调函数
CKFinder 弹出窗口操作并设置回调函数 官方例子参考CKFinderJava-2.4.1/ckfinder/_samples/popup.html 写一个与EXT集成的小例子 Ext.defin ...
- Spring Cache 源码解析
这个类实现了Spring的缓存拦截器 org.springframework.cache.interceptor.CacheInterceptor @SuppressWarnings("se ...
- jffs2系统制作2
http://blog.chinaunix.net/uid-23208702-id-353022.html 1.2. 安装zlib库 由于交叉编译mtd工具时需要zlib.h文件,所以在编译之前先 ...
- 【3C认证】安防产品3C认证
安防产品3C认证作为3C认证的一部分.安防产品即:防范的手段达到或实现安全的目的的设备或器材. 依据<中华人民共和国产品质量法>.<中华人民共和国标准化法>.<中华人民共 ...
- linux 提示符绝对路径
# Turn on checkwinsize shopt -s checkwinsize [ "$PS1" = "\\s-\\v\\\$ " ] & ...