迟到的 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#的书和微软的文档,我觉得对属性讲解比较好理解的就 ...
随机推荐
- Android UI开发神兵利器之Android Asset Studio
Android Asset Studio 这个工具提供了一系列的资源设计实现,很推荐:
- 项目管理实践 -- 健身小管家(Fitness housekeeper)的管理
最近在网上看到一篇文章<王石:我每天都强迫自己做的一件事>,[http://blog.sina.com.cn/s/blog_4dfc1c330102v0d0.html] 原始链接不详. ...
- CentOS 使用yum命令安装Java SDK(openjdk)
CentOS 6.X 和 5.X 自带有OpenJDK runtime environment (openjdk).它是一个在linux上实现开源的java 平台.CentOS yum 命令 安装 ...
- Asp.Net MVC5入门学习系列④
原文:Asp.Net MVC5入门学习系列④ 添加Model且简单的使用EF 对于EF(EntityFramework)不了解的朋友可以去百度文科或者在园子里搜一些简资源看下,假如和我一样知道EF的概 ...
- POJ 2724 Purifying Machine(最大独立集)
POJ 2724 Purifying Machine 题目链接 题意:这题题意有点没看懂.看了别人的题解, 给出m串长度为n的01串. 有些串中可能包括,这种串能够表示两个串,为1 和为0. 反复的算 ...
- 4GB内存原32位系统(x86)取舍问题,显卡共享内存Win8.1完全不用担心
情景:集成显卡 配置: 4G显示3.25GB 此时系统自动将用不到的系统完全共享给显卡(768MB而不是256): 看显卡适配器信息,完全共享给了显卡 解说:上图总可用图形内存 = 图2中备用 + 硬 ...
- Ping域名惊现65.49.2.178
--- 昨天新建的博,早晨起来进去看看,发现无法访问.这… 排错开始,ping域名出现如上图所示结果,请求超时…哪里的问题呢 有时常识是害人的,想起了前两月群里也有人说本地无法访问自己网站,别人能访问 ...
- List environment variables from Command Prompt
Request: List the environment variables from Command Promt To list one varibales , the syntax is lik ...
- Servlet配置load-on-startup
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...
- 使用javaservice 将jboss 注册为服务
近来做项目,需要jboss定期重新启动.不想再看到jboss启动那个黑洞洞的窗口,就想着把它注册为服务,然后在net start.恰好objectweb上有个open source的javaservi ...