介绍

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. 06.深入浅出 Spring Boot - 数据访问之Druid

    代码下载:https://github.com/Jackson0714/study-spring-boot.git 一.Druid是什么? 1.Druid是数据库连接池,功能.性能.扩展性方面都算不错 ...

  2. vue+element 表单封成组件(2)

    今天我们继续把时间选择器,多选框和单选框加上 父组件(在昨天的基础上增加): <template> <el-form :model="ruleForm" ref= ...

  3. vue iview modal弹出框 form表单验证

    一.ref="addApply" :model="addApply" :rules="ruleValidate"   不要忘记prop 二. ...

  4. VS2017配置opencv-4.2.0详细步骤

    VS2017配置opencv-4.2.0详细步骤   1.下载opencv的安装包并解压.下载网址https://sourceforge.net/projects/opencvlibrary/ 图1 ...

  5. MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询

    对于一对一,一对多的关联查询,Mybatis-Plus官方示例(mybatis-plus-sample-resultmap)在处理时,需要编写查询方法及配置resultMap,并且写SQL. 为了简化 ...

  6. 文本编辑器 - Sublime Text 3 换行无法自动缩进的解决方法

    一.换行无法自动缩进的问题,如图: 稍微查了一下网上的办法,是把汉化文件删除,但是会造成菜单栏混乱,简直无法忍受... 那么这里介绍的是另一种解决办法.在用户的热键配置文件(preferences-k ...

  7. Scrapy 入门教程

    Scrapy 是用 Python 实现的一个为了爬取网站数据.提取结构性数据而编写的应用框架. Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 通常我们可以很简单的通过 ...

  8. oracle使用expdp定时备份数据库

    目录 oracle使用expdp备份数据库 备份shell脚本 创建定时任务 oracle使用expdp备份数据库 备份shell脚本 #!/bin/sh #获取当前时间 BACKUPTIME=$(d ...

  9. C++ 判断两个圆是否有交集

    #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include <math.h> #include <easyx.h ...

  10. 搭建私有 Nuget 服务器教程(1)

    对于 .NET 开发者来说,nuget 是必不可少的程序包管理工具.相应地,大部分开发团队都需要在内部搭建 Nuget 服务器,以管理私有 nupkg 包.本教程所使用的 Nuget 服务器,不是微软 ...