迟到的 WPF 学习 —— 依赖项属性
本章学习依赖项属性,英文原文 Dependency Property,它是传统 .Net Framework 属性的扩展,是 WPF 的专属,但所幸使用起来和传统属性几乎一样。WPF 元素所提供的大多数属性都是依赖项属性。
1. 定义依赖项:只能为依赖对象添加依赖项属性,即 DependencyObject,WPF 中大部分元素都继承 DependencyObject 。属性信息应该始终可用,并可能在多个对象间共享访问,因此必须将 Dependency Property 对象设置为与之关联的类的静态字段?我也没太明白,接着往下看解释:
例如,FrameworkElement 类定义了 Margin 属性,所有(继承它的)元素都共享该属性,这意味着在 FrameworkElement 类中应该这样定义 Margin:
public class FrameworkElement:UIElement,...
{
public static readonly DependencyProperty MarginProperty;
...
}
根据约定,依赖项属性的名称在末尾加上“Property”以识别和普通属性的不同。
2. 注册依赖项:使用前先注册,这一步需要确保在任何使用属性的代码前完成,因此必须在与之关联的静态构造函数中完成(readonly 关键字定义了该字段只能在其静态构造中被修改)。WPF 确保 DP 对象不能被直接实例化, 因为 DP 类没有公共构造函数,反而只能使用 DependencyProperty.Register() 方法创建,WPF 还确保其创建之后不能被修改,因为属性的值要作为 Register 方法的参数在静态构造中被设置。
先创建一个 FrameworkPropertyMetadata(该值表示希望通过依赖项属性使用什么服务,如支持数据绑定、动画或日志),然后,再用 DependencyProperty.Register() 注册
3. 像原来一样使用依赖项属性:注册后,使用传统的 .Net 包装一下,WPF 是使用 DependencyObject 基类中定义的 SetValue 和 GetValue 方法,如下:
public Thickness Margin{
set{ SetValue(MarginProperty,value); }
get{ return (Thickness)GetValue(MarginProperty); }
}
提示,在创建属性包装器是,应该只包含对 SetValue 和 GetValue 两个方法的操作,不要额外假如数据验证、事件操作等,因为这有可能会导致这些元素忽略正常的 Set 和 Get。清除属性值有特定的方法,继承自 DependencyObject 的 ClearValue 方法:myElement.ClearValue(FrameworkElement.MarginProperty)
4. 检索属性值:因为依赖项属性依赖于多个属性提供者,每个提供者都有自己的优先级,所以 WPF 以一种逐级检索的方式确定使用哪个值,其层级顺序(从低到高):
(1) 默认值,由 FrameworkPropertyMetadata 设置的值
(2) 通过继承,如果设置了 FrameworkPropertyMetadata.Inherits 标志,并且为包含层次中的某一个元素提供一个值(说实话,这句话没明白)
(3) 来自主题样式的值
(4) 来自项目样式的值
(5) 本地值,即使用代码或XAML直接设置的值
如上所示,可以通过直接应用一个值而覆盖掉整个层次,否则将由列表中前一个可用项确定。
5. 共享依赖项属性:一些类会共享同一个依赖项属性,比如 TextBlock 和 Control 都有 FontFamily 属性,他们指向同一个静态的依赖项属性,该属性实际上是在 TextElement 类中定义的 TextElement.FontFamilyProperty,由 TextElement 的静态构造函数注册,那两个类通过在其静态构造函数中嗲用 DependencyProperty.AddOwner() 方法重用该属性:
TextBlock.FontFamily = TextElement.FontFamilyProperty.AddOwner( typeof( TextBlock ) )
6. 属性验证:不要把验证属性值的代码像原来一样放到设置属性的逻辑中去,因为可能通过 WPF 的属性设置系统直接使用 SetValue 方法设置,从而使验证部分失灵(被绕过了),WPF 提供两种回调方法实现:
(1) ValidateValueCallback 可以接受或拒绝新值,通用用于捕捉违背属性约束的明显错误,可作为 DependencyProperty.Register() 的一个参数提供
(2) CoerceValueCallback 将新值修改为更能被接受的值,通常用于处理本身合法但与原值或某些层级默认值相冲突的新值,该方法作为构造 FrameworkPropertyMetadata 的一个参数提供
当应用程序设置一个依赖项属性时,它们的作用过程是:
(1) CoerceValueCallback 先有机会修改提供的值,或返回 DependencyProperty.UnserValue ,这会完全拒绝修改
(2) 激活 ValidateValueCallback,该方法返回 true 表示接受修改,返回 false 表示拒绝值。方法不能访问为之设置属性的实际对象,意味着,不能检查其它属性值。
(3) 以上两个方法都成功了,触发 PropertyChangedCallback 方法,这是如果希望通知其它类,可以在此触发事件
7. 验证回调:依赖项属性在注册时,Register 方法其中有一个可选参数,就是设置验证回调方法,写法如下
MarginProperty = DependencyProperty.Register("Margin",
typeof(Thickness),typeof(FrameworkElement),metadata,
new ValidateValueCallback(FrameworkElement.IsMarginValid))
最后一句就是验证回调,回调方法必须指向一个接受 object 参数并返回 bool 的方法,也就是说语句中的 IsMarginValid 方法必须是
private static bool IsMarginValid(object value){ }
对于验证回调,有一个限制,就是必须是静态方法且无权访问正在被验证的对象。所能够获得的信息就只是刚被传进来的 value,比如某元素有 Maximum 和 Minimum 两个属性,设置 Maximum 时候应判断不能小于 Minimum,但这在验证回调函数中是不能实现的,因为它不能访问 Minimum 。解决这种情况,可以使用 6 中提到的 CoerceValueCallback,即强制回调。
8. 强制回调:通过 FrameworkPropertyCallback 使用 CoerceValueCallback,如
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.CoerceValueCallback = new CoerceValueCallback( CoerceMaximum ); DependencyProperty.Register( "Maximum",typeof(double),typeof(Rangebase),metadata);
通过 CoerceValueCallback 可以处理互相关联的属性。对于强制回调的应用,在书中有一大段实例说明,忘记的话还是回去翻翻书吧。
迟到的 WPF 学习 —— 依赖项属性的更多相关文章
- WPF的依赖项属性
WPF的依赖项属性 属性与事件是.NET抽象模型的核心部分.WPF使用了更高级的依赖项属性(Dependency Property)功能来替换原来.NET的属性,实现了更高效率的保存机制,还添加了附加 ...
- 学习WPF——初识依赖项属性
入门 首先创建一个依赖项属性 然后绑定父容器的DataContext到这个依赖项的实例 接着绑定子元素的属性到依赖项属性(注意Button的Content属性) 程序最终的运行结果: 说明 首先是 ...
- [转]WPF 依赖项属性
from:http://blog.csdn.net/datoumimi/article/details/8033682 ps:环境限制,发的东西一长就会被拦截,所以删了一部分 UI软件中经常会用到大量 ...
- 浅谈WPF依赖项属性
浅谈WPF依赖项属性 0. 引言 依赖项属性虽然在使用上和CLR属性一样,但是它是WPF特有的,不同于CLR属性.只是封装为我们常用CLR的属性,在语法使用上和CLR属性一样.WPF中一些功能:动画, ...
- 如何在 WPF 中获取所有已经显式赋过值的依赖项属性
原文:如何在 WPF 中获取所有已经显式赋过值的依赖项属性 获取 WPF 的依赖项属性的值时,会依照优先级去各个级别获取.这样,无论你什么时候去获取依赖项属性,都至少是有一个有效值的.有什么方法可以获 ...
- WPF学习系列之二 (依赖项属性)
依赖属性;(dependency property) 它是专门针对WPF创建的,但是WPF库中的依赖项属性都使用普通的.NET属性过程进行了包装.从而可能通过常规的方式使用它们,即使使用他们的代码不 ...
- WPF中的依赖项属性
Form cnblogs 桂素伟 随着WPF的推广,不得不重新拾起WPF来,因为这块的产品越来越多. 只能跟着MSDN来学了,所以想是在这里记录下学习的过程和对知识的理解. 先从最基本的吧,依赖项属性 ...
- WPF中的依赖项属性(转)
出处:https://www.cnblogs.com/axzxs2001/archive/2010/04/25/1719857.html 随着WPF的推广,不得不重新拾起WPF来,因为这块的产品越来越 ...
- WPF教程四:字段、属性、依赖项属性的演变过程
这个章节主要讲解属性是什么,为什么会演变出依赖项属性,依赖属性的优势是什么.以及如何更好的使用属性和依赖项属性. 一.属性 属性是什么. 翻了好几本C#的书和微软的文档,我觉得对属性讲解比较好理解的就 ...
随机推荐
- 在vc正在使用xtremetoolkit接口库-----使用简单的控制
首先,我们需要在StdAfx.h增加头文件: #include "XTToolkitPro.h" #include "XTPResource.h" 在test. ...
- HDU 4005 The war (图论-tarjan)
The war Problem Description In the war, the intelligence about the enemy is very important. Now, our ...
- DM8168 layout
我们学到了以前的系统板的教训,新的版本号DM8168烤... 一级:电源.DM8168.DDR3.FPGA.CPLD.Nandflash.USB.以太网络.SATA.JTAG等待. 的地面电源部充分. ...
- 通过私有协议Chrome浏览器页面打开本地程序
近期方有这样的要求:这两个系统,根据一组Chrome开展,根据一组IE开展,需要Chrome添加一个链接,然后进入IE该系统的开发.这,需要Chrome跳转到创建一个链接IE浏览器指定的页面.同时也实 ...
- 私人定制javascript中数组小知识点(Only For Me)
先上笑话,1.刚看到一个游泳的,想起公司组织去三亚旅游,老板跳海里,各种挣扎,捞上来老板第一句话:我记得我会游泳的啊. 2.媳妇说:老公对不起,我把你新买的自行车撞散架了! 老公:没事宝贝,你若安好, ...
- centos7的安装
初装centos7还是在九月份,那时候关于win7 下centos7硬盘安装的资料很少,现在就好多, 在这里备份下东西吧 首先是安装的时候,关于找从那个地方找image的问题. hda ,sda分别表 ...
- Cocos2d-x学习笔记(14)(更新函数scheduleUpdate、进度计时器CCProgressTo、滚动视图CCScrollView)
一.scheduleUpdate 1.scheduleUpdate:此函数是CCNode的函数,每一个CCNode仅仅要调用scheduleUpdate更新函数,那么这个CCNode就会响应当前类的u ...
- 2014值得期待的Erlang两本新书
在2014年的开头就有这样一个令人振奋的好消息,Erlang有一本新书即将出版 <The Erlang Runtime System>,其作者happi在2013年3月份发布了这本书的写作 ...
- 利用@media screen实现网页布局的自适应,@media screen and
开始研究响应式web设计,CSS3 Media Queries是入门.Media Queries,其作用就是允许添加表达式用以确定媒体的环境情况,以此来应用不同的样式表.换句话说,其允许我们在不改变内 ...
- android项目总体界面架构(可直接复用)
文章解读.效果图.源代码下载链接 http://blog.csdn.net/gao_chun/article/details/37903673