介绍

WPF本身就支持通知、绑定和命令,实现ViewModel和VIew之间的通讯,但相对来说功能比较少,Prism扩充了这些功能并提供更加强有力,简洁的数据绑定和命令。

0 绑定通知

WPF的绑定通知需要实现INotifyPropertyChanged接口,也就是实现一个属性改变事件,用来通知UI属性改变了,让UI更新。该事件需要一个事件参数new PropertyChangedEventArgs(propertyName)传入属性的名字,这样的调用方式比较繁琐。

Prism扩充了WPF的绑定通知。提供了BindableBase 实现了 INotifyPropertyChanged接口,并使用CallerMemberName获取属性名字。这样就解决了属性改变事件调用繁琐的问题。同时在内部还是对相等值进行了过滤。

简单愉快的调用吧

只需要使用SetProperty方法就可以自动更新UI了。

值得注意的是OnPropertyChanged还提供了对Expression的支持

也就是主动调用OnPropertyChanged(()=>this.PropertyName),也可以触发UI响应。

1 命令

DelegateCommand

WPF命令和通知有点类似,命令需要实现ICommand接口,实现Execute方法,命令状态CanExecute和命令状态改变事件。并且WPF只实现了一个RoutedCommand。Prism提供了一个DelegateCommandBase命令基类实现ICommand,并扩充了子类DelegateCommand,大大简化了命令调用方式

看到在基类中有_synchronizationContext线程同步上下文,用来保证命令执行的时候线程同步。

重点关注一下子类中的几个方法

1.ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);

  • 这个命令声明方式,如果命令状态发生变化的时候需要主动调用RaiseCanExecuteChanged方法来触发命令状态改变事件。

2.DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute).ObservesProperty(() => IsEnabled);

  • 可以看到这种声明方式,提供了一个ObservesProperty方法,不需要显示调用命令状态改变事件。

3.DelegateCommandObservesCanExecute = new DelegateCommand(Execute).ObservesCanExecute(() => IsEnabled);

  • 这种声明方法提供ObservesCanExecute方法,直接观测命令状态改变事件和属性。

4.ExecuteGenericDelegateCommand = new DelegateCommand(ExecuteGeneric).ObservesCanExecute(() => IsEnabled);

  • 这是一个使用泛型带参数的声明方式,

看一下内部怎么实现这种简单而强大的功能

通过Expression,内部调用PropertyObserver.Observes()方法并将RaiseCanExecuteChaned方法传入。

在PropertyObserver将Expression保存在一个链表,并每个节点都订阅OnPropertyChanged事件。

CompositeCommand

Prism还提供了一个CompositeCommand命令

这个命令的功能跟其名字一样,就是复合命令,命令集合。

  • 将DelegateCommand实例放到其中,每当调用CompositeCommand调用的时候会调用它保存的所有命令,
  • 命令集合中任何一个命令状态改变,都会触发CompositeCommand命令状态的改变事件,导致CompositeCommand检查集合中所有的命令状态,首先会检查IActiveAware,再检查命令状态,如果任何一个命令状态是False,都会导致组合命令返回False

来看一下源码

注意到,聚合命令也是通过线程上下文保持线程同步,同时看到有检测IActiveAware接口,这个接口是什么意思呢?其实就是查看该命令是否激活。这个接口有一个激活状态属性和一个激活状态改变事件,

只要界面主动调用UpdateCommand.IsActive = true;命令就会被激活并触发复合命令的激活状态改变回调函数

在复合命令的ShouldExcute方法中检查其激活状态,命令集合中没有激活命令,那么复合命令的执行状态也会改变。

命令执行和激活状态都是差不多的接口,有状态和状态改变事件组成,感觉很多地方都有相似的模式,有点像订阅模式,也有点像状态机,包括一些Collection和Storage.

总结

主要讲了下Prism提供的绑定通知和命令,学习到如何在WPF框架基础上做一些封装,如果可能甚至可以自己重新封装一些功能更强大的命令来兼容Prism。

Prism 源码解读5-数据绑定和命令的更多相关文章

  1. Prism 源码解读1-Bootstrapper和Region的创建

    介绍 之前也研究过Prism框架但是一直没有深入理解,现在项目上想把一个Winform的桌面应用程序改造成WPF程序,同时我希望程序是可测试可维护架构良好的,Prism的这些设计理念正好符合我的需求, ...

  2. Prism 源码解读2-View的加载和控制

    介绍 上一篇介绍了Region,这一篇跟Region息息相关,讲一下Region中View的加载方式及控制. 4.ViewDiscovery 在创建好Region后需要将View添加到Region中. ...

  3. Prism 源码解读3-Modules加载

    介绍 在软件开发过程中,总想组件式的开发方式,各个组件之间最好互不影响,独立测试.Prism的Modules很好的满足了这一点. 这个架构图很好了讲解了Prism的Modules的概念 Prism支持 ...

  4. Prism 源码解读4-ViewModel注入

    介绍 介绍一个Prism的MVVM实现,主要介绍Prism如何在WPF上进行的一些封装,以实现MVVM.MVVM到底是什么呢?看一下这一幅经典的图 以前没有ViewModel这个概念,就是将Model ...

  5. Prism 源码解读6-事件聚合

    0 介绍 事件提供的是1对多的绑定,通过委托链实现对订阅者的调用,事件必须要通过发布者调用.同时事件订阅是强引用,事件订阅者的生命周期总是大于等于事件发布者.如果代码中事件很多就会充斥着各种事件的订阅 ...

  6. Prism 源码解读7-导航

    介绍 Prism提供了一个非常强大的功能导航,导航的意思就是指定对应的View显示.这个导航的强大之处有: 可以设置导航前后的动作 可以指定View实例的生命周期,可以是否导航到新的View实例 提供 ...

  7. Laravel 源码解读系列第四篇-Auth 机制

    前言 Laravel有一个神器: php artisan make:auth 能够快速的帮我们完成一套注册和登录的认证机制,但是这套机制具体的是怎么跑起来的呢?我们不妨来一起看看他的源码.不过在这篇文 ...

  8. php-msf 源码解读【转】

    php-msf: https://github.com/pinguo/php-msf 百度脑图 - php-msf 源码解读: http://naotu.baidu.com/file/cc7b5a49 ...

  9. create-react-app源码解读之为什么不搞个山寨版的create-react-app呢?

    最近把 vue-cli@2.x 和 create-react-app 的源码都看了一遍.由于现在官方推荐使用 vue-cli@3.0 ,改动比较大,所以就不写关于 vue-cli 的了(据说是因为 v ...

随机推荐

  1. Python基础知识(day1)

    day1 1.编码 ASCII码 1字节8位 2^8 = 256 位 万国码 unicode 4字节32位 #浪费空间 UTF-8 对unicode进行压缩 2.注释 单行注释 score = inp ...

  2. DIY 作品 及 维修 不定时更新

    手机电池DIY充电宝 2块,优质手机电池加一个升压ic ,焊上一个 usb 母头.比买的强多了. 还能调压,最高调到24V 可以带白光焊台. 更换手机 SIM/SD 卡二合一 贴上高温胶带,吹下来. ...

  3. 等宽字体的妙用-loading 点点点动画

    原理 ch等宽字体 + text-indent 动画负缩进 显示效果如 loading . loading .. loading ... loading . loading .. loading .. ...

  4. CSS 文本截断方案

    单行截断 .ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } 此方法兼容到ie6过.不过只能单行 ...

  5. go学习第五天、运算符

    算术运算符 下表列出了所有Go语言的算术运算符.假定 A 值为 10,B 值为 20 运算符 描述 实例 + 相加 A + B 输出结果 30 - 相减 A - B 输出结果 -10 * 相乘 A * ...

  6. C++ 文件操作 FILE*

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> //编程题:往文件里写入字母表的26个字母. //要求:如果字母对应编码值 是奇数则写 ...

  7. 深度学习与人类语言处理-语音识别(part2)

    上节回顾深度学习与人类语言处理-语音识别(part1),这节课我们将学习如何将seq2seq模型用在语音识别 LAS 那我们来看看LAS的Encoder,Attend,Decoder分别是什么 Lis ...

  8. 原生Canvas循环滚动弹幕(现金红包活动带头像弹幕)

    效果 gif有些糊,可以 在线预览 实现关键点 requestAnimationFrame 循环帧: 绘制单条弹幕,画框子 -> 画头像 -> 写黑色的字 -> 写红色的字, mea ...

  9. .Net Framework 工具Mpgo.exe与Ngen.exe

    首先放出官方MSDN的文档地址 Mpgo.exe 主要用于分析程序集启动时需要哪些东西,然后将信息反馈给NGen.exe 来更好的优化本机映像,使得应用程序启动更快,工作集缩小.准备发布时,用MPGO ...

  10. StringBuilder内存碎片对性能的影响

    StringBuilder内存碎片对性能的影响 TL;DR: StringBuilder内部是由多段char[]组成的半自动链表,因此频繁从中间修改StringBuilder,会将原本连续的内存分隔为 ...