还需要些什么呢

在前面几篇博客中我们尝试去实现了MVVM中的数据绑定、命令绑定和事件绑定。貌似实现的差不多了。我最早尝试用MVVM去开发的时候也是这么想的,没有用第三方框架,甚至只是实现了数据绑定和命令绑定就开搞了,遇到需要订阅事件的时候就把代码写在后台。那时候经常自我洗脑:设计模式是死的,人是活的,不能犯教条主义错误,后台写点代码影响不大。我确实很好的贯彻了这个思想,逻辑自然是乱得一塌糊涂。后来认真学习了下,实现了事件绑定,感觉好了很多。但确走向了另一个极端,后台代码多写一行都会感觉很不爽。还有就是View和ViewModel的依赖,例如当需要在ViewModel中打开窗口,给窗口传值,在窗口关闭后获取返回值时,打开窗体的动作在ViewModel中进行吗?这样ViewModel又产生了对View的依赖了。还有当主窗体按下一个按钮,然后需要另外一个窗体做出响应的时候,窗体间要如何通信。当在ViewModel中使用其它线程影响到UI时怎么处理。这篇博客主要对这些问题简单说明一下。

View和ViewModel的通信

消息通信的方式主要受到MVVMLight的启发,MVVMLight实现了一套略有复杂的消息通信,包含了定类型发送、分组发送、发送给包含继承类型的目标、广播等。就目前我做的几个小项目来说,View和ViewModel通信本身用的就不是那么频繁,需求也不算旺盛,所以自己实现了一套比较简易的消息通信。View在实例化的时候注册消息,通过一个列表保存注册的消息,消息在发送的时候根据条件从列表中找到相应的消息并执行操作,如下图所示:

消息发送和处理:

比较奇怪的是为什么要引入一个消息注册器,在View的后台代码中直接注册不就可以了吗?好吧,其实最初的想法确实比较强迫症,只是单纯的不想在后台中写入太多的代码(我真不是处女座),这样看上去似乎更高端。不过后来想了下,View对ViewModel(虽然不是接口)和消息注册器实际上都算是一种依赖,而且View对ViewModel和消息注册器的依赖都是唯一的,也就是说一个View只有一个ViewModel和一个消息注册器。这样可以用控制反转的方式把对ViewModel和消息注册器的依赖一起注入进来,而且在注入过程中可以顺便配置ViewModel的Dispatcher以方便跨线程修改UI,也可以给ViewModel配置单独的MessageManager让View和ViewModel的通信进入另一个次元,不受其他消息干扰。这些在讨论ViewModel依赖注入的时候将会尝试。

关于跨线程修改UI

这个顺带提一下,因为实现起来很简单。在ViewModel中有时会遇到使用其它线程修改UI的情况,我之前是通过 App.Current.MainWindow.Dispatcher来获取UI线程的调度器的。当然也可以把UI线程的调度器保存到一个静态变量中以便随时访问。不过我一直没搞明白MaiWindow的Dispatcher和非MainWindow的Dispatcher有什么区别,不过还是在ViewModel的基类中加入了Dispatcher这个属性,这样在给View注入ViewModel的时候可以把ViewModel的Dispatcher设置为绑定的View的Dispatcher,虽然并不太清楚这有什么卵用 -_-|||

MVVM模式View和ViewModel的通信的更多相关文章

  1. MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信

    MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...

  2. js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别

    MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...

  3. WPF学习笔记:MVVM模式下,ViewModel如何关闭View?

    原文:http://blog.csdn.net/leftfist/article/details/32349731 矫枉过正,从一个极端走向另一个极端.MVVM模式,View只负责呈现,虽然也有后台代 ...

  4. MVVM模式下,ViewModel和View,Model有什么区别

    摘自正美的5群 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就是展现出来的用户界面. 基本上,绝大多数软件所做的工 ...

  5. wpf mvvm模式下 在ViewModel关闭view

    本文只是博主用来记录笔记,误喷 使用到到了MVVM中消息通知功能 第一步:在需要关闭窗体中注册消息 public UserView() { this.DataContext = new UserVie ...

  6. MVVM之View和ViewModel的关联

    概要: 将所有的VM在加载到Application的Static Resource中,然后在View中用标签指定. 实现: 1)采用特性指定要添加到StaticResource中的对象 public  ...

  7. MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息

    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...

  8. MVVM模式用依赖注入的方式配置ViewModel并注册消息

    最初的想法 这次主要讨论下给View指定ViewModel的事情.一般来说给View指定ViewModel常用的方式有两种,一种是在View的后台代码中写DataContext = new ViewM ...

  9. MVVM模式解析和在WPF中的实现(三)命令绑定

    MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

随机推荐

  1. [洛谷P3175][HAOI2015]按位或

    题目大意:刚开始有一个数$x=0$,每秒钟有一个数$y\in[0,2^n)(n\leqslant20)$按一定概率随机出现,数$i$的概率为$p_i$,保证$\sum\limits_{i=0}^{2^ ...

  2. 浅谈Tarjan算法及思想

    在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连 ...

  3. 【bzoj2733】 HNOI2012—永无乡

    http://www.lydsy.com/JudgeOnline/problem.php?id=2733 (题目链接) 题意 给出图上$n$个点,每个点有一个点权,每次询问一个连通块中点权第$K$小的 ...

  4. 《Linux内核设计与实现》学习总结 Chap5

    一.与内核通信 1.系统调用在用户空间进程和硬件设备之间添加了一个中间层. 作用: 1)为用户空间提供了一种硬件的抽象接口. 2)系统调用保证了系统的稳定和安全. 3)每个进程都运行在虚拟系统中,而在 ...

  5. [SDOI2009] HH去散步 (矩阵乘法)

    link $solution:$ 将边化为点后重新建矩阵,跑$T-1$幂即可(因为跑的是新边). 最后直接找与$x,y$所相连的边即可. #include<iostream> #inclu ...

  6. bzoj1874 [BeiJing2009 WinterCamp]取石子游戏

    1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 925  Solved: 381[ ...

  7. Python如何引入自定义模块?

    Python运行环境在查找库文件时是对 sys.path 列表进行遍历,如果我们想在运行环境中注册新的类库,主要有以下四种方法: 1.在sys.path列表中添加新的路径.这里可以在运行环境中直接修改 ...

  8. windows10下基于vs2015的 caffe安装教程及python接口实现

    啦啦啦:根据网上的教程前一天安装失败,第二天才安装成功.其实caffe的安装并不难,只是网上的教程不是很全面,自己写一个,留作纪念. 准备工作 Windows10 操作系统 vs2015(c++编译器 ...

  9. (转) linux下vim和bash配置文件

    1.注释版  ~/.vimrc "去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限 set nocompatible set autoread " 文件修改之后自动载入 ...

  10. HTTP协议(2)-------- 网络编程

    1. HTTP请求格式 做过Socket编程的人都知道,当我们设计一个通信协议时,“消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干.HTTP协议传输的消息 ...