MVVM模式用依赖注入的方式配置ViewModel并注册消息
最初的想法
这次主要讨论下给View指定ViewModel的事情。一般来说给View指定ViewModel常用的方式有两种,一种是在View的后台代码中写DataContext = new ViewModel(),还有一种是在XAML中指定View的DataContext。这两种方式都使得View对ViewModel产生了依赖,这种情况下可以考虑用依赖注入的方式使取消View对ViewModel的直接依赖。依赖注入一般来说可以通过构造函数注入、通过设置属性注入,这两种方法对于View来说都不合适。因此可以使用IoC Container,让View主动去获取对应的ViewModel。
其实给View指定一个ViewModel并不属于频繁的操作,而且改起来也很容易,费半天劲搞个依赖注入确实不太至于。就像上篇文章中废了半天劲搞了个View和ViewModel的通信一样,用到的概率比较小,而且也有别的方式解决,虽然那种方式并不符合MVVM模式。不过View除了依赖ViewModel之外对消息注册器也是会产生依赖的,而且某种类型的View一般来说都依赖固定类型的ViewModel和消息注册器,因此可以一次注入两个依赖,这样貌似就值了,至少我认为是值了,所以有了ViewModelManager这个类。
ViewModel和MessageManager的依赖注入
使用静态类ViewModelManager来当作IoC Container。往IoC Container里注册依赖关系一般有两种方式,一种是将依赖关系以某种形式(例如xml)保存在外部,一种是在程序中注册到一个列表里。我采取第二种做法,因为比较容易:)
程序在启动时使用ViewModelManager.Register将依赖关系注册到ViewModelManager中,View在构造函数中调用ViewModelManager.SetViewModel(this);来设置View的DataContext并通过依赖的消息注册器注册消息,消息注册器可以为空,代表View不接收消息。它们的关系如图所示:

需要说明的有两个地方:
一个是View和ViewModel的对应关系。一般来说一个View对应着一种ViewModel,这样注册起来是没问题的。但这个并不绝对,理论上来说一个View可以将DataContext设置为任意ViewModel,如果一个View可以设置多种ViewModel该如何处理呢,这时候可以在ViewModelManager注册时添加Token属性,然后用SetViewModel(this,token)的方式指定特定的ViewModel为DataContext。
另一个是消息注册的范围。因为一般来说ViewModel都是和绑定的View通信。所以默认情况下,消息注册到单独一个MessageManager中,这个MessageManager保存ViewModel中,ViewModel使用这个MessageManager发送消息,发送的消息由View接收。但如果需要和其他View通信,需要把消息注册到MessageManager.Default中,这个对象是static的,要达到这个目的只要在View设置ViewMode时这样来SetViewModel(this,isGlobalMsg:true)即可。如果ViewModel又想和绑定的View单独通信,有时候还需要和别的View通信,可以在消息注册器中注册时将需要单独通信的消息设置一个Group,ViewModel在发送消息时加一个Group过滤一下即可。一个Group可以理解为消息的单独一个通道。
顺带一提,好吧只是顺带一提的是,在给View注入ViewModel时,顺便把ViewModel的UIDispatcher属性设置为了View的Dispatcher,虽然我不知道这有什么用。但这样在ViewModel中使用UIDispatcher时即为相关的View的Dispatcher。如果要使用MainWindow的Dispatcher可以通过DispatcherHelper.Dispatcher或者App.Current.MainWindow.Dispatcher获得。
写在最后
到此为止我能想到的MVVM框架的功能算是基本实现了,遇到的需求十分有限,才能也十分有限,能想到的就这几个了,欢迎回复讨论,也欢迎加我QQ16141860交流。之前一直是在TestArea这个仓库里进行测试,现在这个小框架整理了下,放到AyxMVVM仓库里了。现在有些想法还不太成熟,使用过程中遇到问题也会随时修正,以后就都修改到AyxMVVM中了,TestArea中的MyMVVM不再维护了。另外给仓库起名真是件麻烦事,干脆统一都用Ayx+XXX的方式,这样既容易重复的概率又十分小。Ayx是我名字拼音的首字母,想想看以拼音A开头的姓氏之少就能想到几乎不会出现重复了。最后,10月6日看了微软的秋季产品发布会后信仰充值成功。对UWP十分感兴趣,下一步打算学习一下。
MVVM模式用依赖注入的方式配置ViewModel并注册消息的更多相关文章
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- Spring(八):Spring配置Bean(一)BeanFactory&ApplicationContext概述、依赖注入的方式、注入属性值细节
在Spring的IOC容器里配置Bean 配置Bean形式:基于xml文件方式.基于注解的方式 在xml文件中通过bean节点配置bean: <?xml version="1.0&qu ...
- spring 配置bean的方法及依赖注入发方式
Bean 的配置方式:通过全类名(反射).通过工厂方法(静态工厂方法 & 实例工厂方法).FactoryBean 这里依据全类名配置bean <bean id="helloWo ...
- Spring4学习回顾之路03—XML配置Bean ,依赖注入的方式
配置Bean的形式可以基于XML文件的方式,也可以基于注解的方式,而Bean的配置方式可以通过全类名(反射),通过工厂方式和FactoryBean. XML形式 <?xml version=&q ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- MVC中使用泛型仓储模式和依赖注入
在ASP.NET MVC中使用泛型仓储模式和依赖注入,实现增删查改 原文链接:http://www.codeproject.com/Articles/838097/CRUD-Operations-Us ...
- Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor
Webservice WCF WebApi 注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...
- 在MVC中使用泛型仓储模式和依赖注入实现增删查改
标签: 原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository ...
随机推荐
- MT【157】至少一个小于1
若函数$f(x)=x^2+ax+b$有两个不等实数根$x_1,x_2$,且$1<x_1<x_2<3$,那么$f(1),f(3)中$ ( )A.只有一个小于1 B.至少 ...
- 手机H5显示一像素的细线
手机屏幕分辨率的问题,导致h5的1像素看起来比较粗,网上找了一个办法,记下来 主要就是通过scale来缩小宽度 .line1px{ border: none; border-botto ...
- PHP是什么?
PHP是什么? PHP是一门后端动态解释型计算机高级语言,一般用来编写或者生成动态网页,主要负责数据的处理与渲染.(这里是指用PHP嵌入网页里面的形式,现在可以直接用一些JS的框架去渲染网页数据了,P ...
- [BZOJ1500][NOI2005]维修数列 解题报告 Splay
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- 【bzoj4231】回忆树
题解: 树上的串匹配,模式串的总长$|S|$,令$\overline {S} $为$S$的反串: 对$S$和$\overline {S} $分别建自动机 $u -> v$可以分成三个部分去统计 ...
- 2019PKU\THU WC题解
PKU: 机试: d1t1: 考虑拓扑序的合法性,每个点的入边必须先加入.f[S]表示先出来的是S集合的点,对应边的方案数.加入x的时候,把入边方向确定,出边自然后面会确定的 2^n*n d1t2: ...
- python之旅:面向对象的程序设计
一 面向对象的程序设计的由来 面向对象设计的由来见概述:http://www.cnblogs.com/moyand/p/8784210.html 二 什么是面向对象的程序设计及为什么要有它 面向过程的 ...
- poj 3294 后缀数组 多字符串中不小于 k 个字符串中的最长子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16223 Accepted: 4763 Descr ...
- Kubernetes 1.5 配置dns
在kubernetes1.2的时候,采用了skydns + kube2dns +etcd的方式来部署dns.而从1.3开始,则部署方式有了一点儿变化,将skydns和kube2dns封装到了一个容器镜 ...
- string 中的一些优化事项
1.1 fmt vs "+" (无转义) import ( "testing" "fmt" ) var ( str = "he ...