MVVM模式解析和在WPF中的实现(六)

用依赖注入的方式配置ViewModel并注册消息

系列目录:

MVVM模式解析和在WPF中的实现(一)MVVM模式简介

MVVM模式解析和在WPF中的实现(二)数据绑定

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

MVVM模式解析和在WPF中的实现(四)事件绑定

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

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

0x00 最初的想法

这次主要讨论下给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这个类。

0x01 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获得。

0x02 写在最后

到此为止我能想到的MVVM框架的功能算是基本实现了,遇到的需求十分有限,才能也十分有限,能想到的就这几个了,欢迎回复讨论,也欢迎加我QQ16141860交流。之前一直是在TestArea这个仓库里进行测试,现在这个小框架整理了下,放到AyxMVVM仓库里了。现在有些想法还不太成熟,使用过程中遇到问题也会随时修正,以后就都修改到AyxMVVM中了,TestArea中的MyMVVM不再维护了。另外给仓库起名真是件麻烦事,干脆统一都用Ayx+XXX的方式,这样既容易重复的概率又十分小。Ayx是我名字拼音的首字母,想想看以拼音A开头的姓氏之少就能想到几乎不会出现重复了。最后,10月6日看了微软的秋季产品发布会后信仰充值成功。对UWP十分感兴趣,下一步打算学习一下。

0x03 关于AyxMVVM

https://github.com/durow/AyxMVVM

MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息的更多相关文章

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

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

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

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

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

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

  4. 在WPF中使用依赖注入的方式创建视图

    在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...

  5. WPF中使用文件浏览对话框的几种方式

    原文:WPF中使用文件浏览对话框的几种方式 WPF本身并没有为我们提供文件浏览的控件, 也不能直接使用Forms中的控件,而文件浏览对话框又是我们最常用的控件之一. 下面是我实现的方式 方式1: 使用 ...

  6. 示例:WPF中自定义MessageService应用DialogHost、Snackbar、NotifyIcon显示各种场景提示消息

    原文:示例:WPF中自定义MessageService应用DialogHost.Snackbar.NotifyIcon显示各种场景提示消息 一.目的:不同交互场景需要提示不同的消息,不同的消息需要用不 ...

  7. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

  8. 轻松了解Spring中的控制反转和依赖注入(二)

    紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...

  9. Spring学习(三)——Spring中的依赖注入的方式

    [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...

随机推荐

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...

  3. Velocity笔记--使用Velocity获取动态Web项目名的问题

    以前使用jsp开发的时候,可以通过request很轻松的获取到根项目名,现在换到使用velocity渲染视图,因为已经不依赖servlet,request等一些类的环境,而Web项目的根项目名又不是写 ...

  4. gulp初学

    原文地址:gulp初学 至于gulp与grunt的区别,用过的人都略知一二,总的来说就是2点: 1.gulp的gulpfile.js  配置简单而且更容易阅读和维护.之所以如此,是因为它们的工作方式不 ...

  5. C++整数转字符串的一种方法

    #include <sstream> //ostringstream, ostringstream::str() ostringstream stream; stream << ...

  6. CSS3 @keyframes 动画

    CSS3的@keyframes,它可以取代许多网页动画图像,Flash动画,和JAVAScripts. CSS3的动画属性 下面的表格列出了 @keyframes 规则和所有动画属性: 浏览器支持 表 ...

  7. css_02之盒模型、渐变

    1.框模型:盒模型,①对象实际宽度=左右外边距+左右边框+左右内边距 + width:②对象实际高度=上下外边距+上下边框+上下内边距 + height: 2.外边距:margin:取值:①top(上 ...

  8. Oracle第一步

    Oracle 启动数据库 Startup [NOMOUNT|MOUNT|OPEN|FORCE] [restrict] [pfile=filename] 启动实例,加载数据库,启动数据库 oRACLE关 ...

  9. 微信开发笔记(accesstoken)

    access_token分两种 一种是公众号权限获取用,调用cgi-bin接口 ,此种token一个公众号同时只有一个,用这一个就够了. 服务器最好缓存. 用这个token前提是用户关注了此公众号. ...

  10. 关于sql server 2005存储过程的写法

    打开数据库的SQL Server Managerment Studio---->数据库----->打开数据库会看见"可编程行"------->打开有存储过程--- ...