WPF入门教程系列十一——依赖属性(一)
一、依赖属性基本介绍
本篇开始学习WPF的另一个重要内容依赖属性。
大家都知道WPF带来了很多新的特性,其中一个就是引入了一种新的属性机制——依赖属性。依赖属性出现的目的是用来实现WPF中的样式、自动绑定及实现动画等特性。依赖属性的出现是WPF这种特殊的呈现原理派生出来的,与.NET普通属性不同的是,依赖属性的值是依靠多个提供程序来判断的,并且其具有内建的传递变更通知的能力。
依赖属性基本应用在了WPF的所有需要设置属性的元素。依赖属性根据多个提供对象来决定它的值 (可以是动画、父类元素、绑定、样式和模板等),同时这个值也能及时响应变化。
依赖属性就是可以自己没有值,并能够通过Binding从数据源获 取值(依赖在别人身上)的属性。拥有依赖属性的对象被称为“依赖对象”。依赖项属性的重点在于“依赖”二字,既然是依赖了,也就是说:依赖项属性的值的改变过程一定与其它对相关,不A依赖B就B依赖A,或者相互依赖。
说白了,所谓依赖,主要应用在以下地方:
1、双向绑定。有了这个,依赖项属性不用写额的代码,也不用实现什么接口,它本身就俱备双向绑定的特性,比如,我把员工对象的姓名绑定到摇文本框,一旦绑定,只要文本框中的值发生改变,依赖项属性员工姓名也会跟着变化,反之亦然;
2、触发器。这个东西在WPF中很重要,比如,一个按钮背景是红色,我想让它在鼠标停留在它上面是背景变成绿色,而鼠标一旦移开,按钮恢复红色。
如果在传统的Windows编程中,你一定会想办法弄一些事件,或者委托来处理,还要写一堆代码。告诉你,有了依赖项属性,你将一行代码都不用写,所有的处理均由WPF属性系统自动处理。而触发器只是临时改变属性的值,当触完成时,属性值自动被“还原”。
3、附加属性。附加属性也是依赖项属性,它可以把A类型的的某些属性推迟到运行时根据B类型的具体情况来进行设置,而且可以同时被多个类型对象同时维护同一个属性值,但每个实例的属性值是独立的。
4、A属性改变时,也同时改变其它属性的值,如TogleButton按下的同时,弹出下拉框。
与传统的CLR属性和面向对象相比依赖属性有很多新颖之处,其中包括:
1、新功能的引入:加入了属性变化通知,限制、验证等等功能,这样就可以使我们更方便的实现我们的应用,同时也使代码量大大减少了,许多之前不可能的功能都可以轻松的实现了。
2、 节约内存:在WinForm等项目开发中,你会发现UI控件的属性通常都是赋予的初始值,为每一个属性存储一个字段将是对内存的巨大浪费。WPF依赖属性 允许对象在被创建的时候并不包含用于存储数据的空间(即字段所占用的空间)、只保留在需要用到数据的时候能够获得默认值。借用其它对象的数据或者实
时分配空间的能力----这种对象称为依赖对象而他这种实时获取数据的能力则依靠依赖属性来实现。在WPF开发中,必须使用依赖对象作为依赖属性的宿主,
使二者结合起来,才能形成完整的Binding目标被数据所驱动。。
3、支持多个提供对象:我们可以通过多种方式来设置依赖属性的值。同时其内部可以储存多个值,配合Expression、Style、Animation等可以给我们带来很强的开发体验。
在.NET当中,对于属性是大家应该很熟悉,封装类的字段,表示类的状态,编译后被转化为对应的get和set方法。属性可以被类或结构等使用。 一个简单的属性如下,也是我们常用的写法:
public class Student { string m_Name; public string Name { get { return m_Name; } set { m_Name = value; } } static Student() { } }
依赖属性与普通的.NET属性的区别是普通的.NET属性定义只需要定义其set和get区块的赋值与设置。那么依赖属性应该怎么定义呢?依赖属性和属性到底有什么区别和联系呢?其实依赖属性的实现也很简单,按以下步骤做就可以了:
第一步: 让自己的类继承自 DependencyObject基类。在WPF中,几乎所有的UI元素都继承自DependencyObject,这个类封装了对依赖属性的存储及 访问等操作,使用静态类型与依赖属性的内部存储机制相关。WPF处理依赖属性不再像普通.NET属性那样将属性值存储到一个私有变量中,而是使用一个字典 型的变量来存放用户显示设置的值。
第二步:依赖属性的定义必须使用 public static 声明一个 DependencyProperty的变量,并且有一个Property作为后缀,该变量才是真正的依赖属性 。例如下面的代码定义了一个依赖属性NameProperty:
public static readonly DependencyProperty NameProperty;
第三步:在静态构造函数中向属性系统注册依赖属性,并获取对象引用。依赖属性是通过调用DependencyProperty.Register静态方法创建,该方法需要传递一个属性 名称,这个名称非常重要,在定义控件Style和Template的时候,Setter的Property属性填入的值就是注册依赖属性时使用的名称。propertyType指明了依赖属性实际的类型,ownerType指明了是哪个类注册了此依赖属性,最后typeMetadata存放了一些依赖属 性的元信息,包括依赖属性使用的默认值,还有属性值发生变更时的通知函数。例如,下面的代码注册了依赖属性。
NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student), new PropertyMetadata("名称", OnValueChanged));
第四步:在前面的三步中,我们完成了一个依赖属性的注册,那么我们怎样才能对这个依赖属性进行读写呢?答案就是提供一个依赖属性的实例化包装属性,通过这个属性来实现具体的读写操作。和CLR属性不同,依赖属性不是直接对私有变量的操纵,而是通过GetValue()和SetValue()方法来操作属性值的,可以使用标准的.NET属性定义语法进行封装,使依赖属性可以像标准属性那样来使用,代码如下。
public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } }
根据前面的四步操作,我们就可以写出下面的代码:
public class Student : DependencyObject { //声明一个静态只读的DependencyProperty字段 public static readonly DependencyProperty NameProperty; static Student() { //注册我们定义的依赖属性Name NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student), new PropertyMetadata("名称", OnValueChanged)); } private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { //当值改变时,我们可以在此做一些逻辑处理 } //属性包装器,通过它来读取和设置我们刚才注册的依赖属性 public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } } }
总结:我们一般.NET属性是直接对类的一个私有属性进行封装,所以读取值的时候,也就是直接读取这个字段;而依赖属性则是通过调用继承自DependencyObject的GetValue()和SetValue来进行操作,它实际存储在DependencyProperty的一个IDictionary的键-值配对字典中,所以一条记录中的键(Key)就是该属性的HashCode值,而值(Value)则是我们注册的DependencyProperty。
WPF入门教程系列十一——依赖属性(一)的更多相关文章
- WPF入门教程系列十三——依赖属性(三)
四. 只读依赖属性 在以前在对于非WPF的功能来说,对于类的属性的封装中,经常会对那些希望暴露给外界只读操作的字段封装成只读属性,同样在WPF中也提供了只读属性的概念,如一些 WPF控件的依赖属性是只 ...
- WPF入门教程系列二十三——DataGrid示例(三)
DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...
- WPF入门教程系列三——Application介绍(续)
接上文WPF入门教程系列二——Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...
- WPF入门教程系列二——Application介绍
一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...
- WPF入门教程系列(二) 深入剖析WPF Binding的使用方法
WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...
- WPF入门教程系列(一) 创建你的第一个WPF项目
WPF入门教程系列(一) 创建你的第一个WPF项目 WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知 ...
- WPF入门教程系列一
WPF入门教程 一. 前言 公司项目基于WPF开发,最近项目上线有点空闲时间写一篇基于wpf的基础教材,WPF也是近期才接触,学习WPF也是在网上查资料与微软的MSDN进行学习,写本博客的目为了温 ...
- WPF入门教程系列十四——依赖属性(四)
六.依赖属性回调.验证及强制值 我们通过下面的这幅图,简单介绍一下WPF属性系统对依赖属性操作的基本步骤: 借用一个常见的图例,介绍一下WPF属性系统对依赖属性操作的基本步骤: 第一步,确定Base ...
- WPF入门教程系列十二——依赖属性(二)
二. 依赖属性的优先级 由于WPF 允许我们可以在多个地方设置依赖属性的值,所以我们就必须要用一个标准来保证值的优先级别.比如下面的例子中,我们在三个地方设置了按钮的背景颜色,那么哪一个设置才会是最终 ...
随机推荐
- jackson json转list
今天项目中用到了jackson,经理说效率高一些,所以就开始用起来,一开始json转对象,对象转json还是很简单的,但也还是有一些问题,后来加了一点配置属性就没有报错了 ObjectMapper m ...
- 【计算几何】bzoj1043 [HAOI2008]下落的圆盘
n^2枚举圆盘,用两圆圆心的向量的极角+余弦定理求某个圆覆盖了该圆的哪一段区间(用弧度表示),最后求个区间并. 注意--精度--最好再累计区间的时候,把每个区间的长度减去EPS,防止最后覆盖的总区间超 ...
- 如何解决WebService参数传递中文乱码问题
1,问题由来 我的主要工作是负责统一适配平台这块,主要任务是提供给客户统一的调用接口,客户使用这个接口可以通过我们再调不同厂家的接口.主要流程如下: 现在客户那边传来的请求报文里面包含中文,使用web ...
- EDA技术与ASIC设计和FPGA开发有什么关系?FPGA在ASIC设计中有什么用途?
利用EDA技术进行电子系统设计的最后目标是完成专用集成电路ASIC的设计和实现:FPGA和CPLD是实现这一途径的主流器件.FPGA和CPLD通常也被称为可编程专用IC,或可编程ASIC.FPGA和C ...
- 利用CSS3实现圆角的outline效果的教程
一.首先,outline是个很牛的东西1. border近亲outline和border是近亲,为什么这么讲呢?首先,都是给元素外面套框框的:其次,支持的属性值几乎都是一样的,例如,outline-s ...
- 在WPF的WebBrowser控件中屏蔽脚本错误的提示
在WPF中使用WebBrowser控件显示网页时,经常会报脚本错误的提示,如何屏蔽掉这些错误提示呢.方法是定义如下方法: public void SuppressScriptErrors(WebBro ...
- 【转】WIN32 控制台程序
http://blog.csdn.net/houmin0036/article/details/7702236 win32控制台项目指在32位Windows命令提示符(即所谓的dos)环境下运行的应用 ...
- MySQL JDBC 出现多个 SHOW VARIABLES 语句。
一次偶然的机会,show processlist 的时候,发现有个 Client 一直在执行 "mysql-connector-java-5.1.21 ( Revision: ${bzr. ...
- highcharts 当Y轴全部没有数据的时候 数据标签显示最下面 而不是居中显示
yAxis: {min: 0,minRange: 1}
- C++混合编程之idlcpp教程Python篇(7)
上一篇在这 C++混合编程之idlcpp教程Python篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与PythonTutorial4工程相似,工程PythonTutorial5中,同 ...