【转】【WPF】关于依赖属性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的执行顺序
三个回调对应依赖属性的验证过程,改变过程和强制转换过程。
class Dobj : DependencyObject
{
//依赖属性包装
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
} //注册依赖属性
//注意依赖属性默认值是:71
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(Dobj), new PropertyMetadata(, PropertyChanged, CoerceValue), ValidateValue); //属性改变
static void PropertyChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
{
Debug.WriteLine(String.Format("PropertyChanged - 属性:{0} 新值:{1} 旧值:{2}", e.Property.Name, e.NewValue, e.OldValue));
} //强制转换
static object CoerceValue(DependencyObject dobj, object newValue)
{
Debug.WriteLine(String.Format("CoerceValue - {0}", newValue));
return newValue;
} //验证
static bool ValidateValue(object obj)
{
Debug.WriteLine(String.Format("ValidateValue - {0}", obj));
return true;
}
}
当仅仅定义一个新对象时:
var dobj = new Dobj();
调试下输出:
ValidateValue -
ValidateValue -
验证过程被执行了两次,我不知道为什么这样。
接着修改这个对象的属性。
var dobj = new Dobj();
dobj.MyProperty = ;
输出:
ValidateValue -
ValidateValue -
ValidateValue -
CoerceValue -
PropertyChanged - 属性:MyProperty 新值: 旧值:
默认值被验证了两遍,接着验证新值,强制转换,最后属性改变回调。
接下来修改一下验证回调,把返回值改为false。
//验证
static bool ValidateValue(object obj)
{
Debug.WriteLine(String.Format("ValidateValue - {0}", obj));
if ((int)obj == )
return false;
return true;
}
赋值语句(SetValue方法)会抛出ArgumentException异常,消息:’999′ is not a valid value for property ‘MyProperty’.(999并不是MyProperty属性的合法值)。

下面要做到内容是创建一个当前依赖对象的继承类,并改写父类依赖属性的元数据。
代码:
//继承原来的依赖对象
class SuperDobj : Dobj
{
static SuperDobj()
{
//改写父类依赖属性的元数据,默认值改成81
Dobj.MyPropertyProperty.OverrideMetadata(typeof(SuperDobj), new PropertyMetadata(, PropertyChanged, CoerceValue));
} //属性改变
static void PropertyChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
{
Debug.WriteLine(String.Format("SuperDobj.PropertyChanged - 属性:{0} 新值:{1} 旧值:{2}", e.Property.Name, e.NewValue, e.OldValue));
} //强制转换
static object CoerceValue(DependencyObject dobj, object newValue)
{
Debug.WriteLine(String.Format("SuperDobj.CoerceValue - {0}", newValue));
if ((int)newValue == )
throw new Exception("test");
return newValue;
}
}
还是像刚才,先定义一个对象:
var superdobj = new SuperDobj();
输出:
ValidateValue -
ValidateValue -
ValidateValue –
父类和子类的验证都要执行一遍。
接着设置子类的依赖属性:
var superdobj = new SuperDobj();
superdobj.MyProperty = ;
输出:
ValidateValue -
ValidateValue -
ValidateValue -
ValidateValue -
SuperDobj.CoerceValue -
PropertyChanged - 属性:MyProperty 新值: 旧值:
SuperDobj.PropertyChanged - 属性:MyProperty 新值: 旧值:
这个结果很有意思。
看来子类和父类的验证和属性改变回调都会依次被调用,但是强制转换只调用子类的。
事实上属性元数据此时会调用PropertyMetadata.Merge方法来合并多个属性元数据。可以参考MSDN:http://msdn.microsoft.com/zh-cn/library/system.windows.propertymetadata.merge.aspx
原文地址:https://www.mgenware.com/blog/?p=188
【转】【WPF】关于依赖属性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的执行顺序的更多相关文章
- WPF的依赖属性
Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR)属性的功能,这些服务通常统称为 WPF 属性系统.由 WPF 属 ...
- WPF的依赖属性和附加属性(用法解释较全)
转:https://www.cnblogs.com/zhili/p/WPFDependencyProperty.html 一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己 ...
- wpf 的依赖属性只能在loaded 事件之后才能取到
wpf 的依赖属性只能在loaded 事件之后才能取到,在构造函数的 InitializeComponent(); 之后取不到 wpf 的依赖属性只能在loaded 事件之后才能取到,在构造函数的 ...
- WPF 中依赖属性的继承(Inherits)
WPF中依赖属性的值是是可以设置为可继承(Inherits)的,这种模式下,父节点的依赖属性会将其值传递给子节点.例如,数据绑定中经常使用的DataContextProperty: var host ...
- WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性
原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? ...
- [转]WPF的依赖属性是怎么节约内存的
WPF升级了CLR的属性系统,加入了依赖属性和附加属性.依赖属性的使用有很多好处,其中有两点是我认为最为亮眼的: 1)节省内存的开销; 2)属性值可以通过Binding依赖于其它对象上,这就使得我的数 ...
- WPF利用依赖属性和命令编写自定义控件
以实例讲解(大部分讲解在代码中) 1,新建一个WPF项目,添加一个用户控件之后在用户控件里面添加几个控件用作测试, <UserControl x:Class="SelfControlD ...
- WPF: 只读依赖属性的介绍与实践
在设计与开发 WPF 自定义控件时,我们常常为会控件添加一些依赖属性以便于绑定或动画等.事实上,除了能够添加正常的依赖属性外,我们还可以为控件添加只读依赖属性(以下统称"只读属性" ...
- WPF 自定义依赖属性
原博客地址:http://www.cnblogs.com/DebugLZQ/archive/2012/11/30/2796021.html DependencyObject和Dependen ...
随机推荐
- eclipse再见,android studio 新手新手教程(一)基本设置
写在前面: 作为一个刚半仅仅脚踏入android开发的新手,在使用eclipse开发了两个自我感觉不甚成熟的商城类app之后.遇到了一些问题,总结为例如以下: 1,代码复用性. findviewByI ...
- 菜鸟学数据库(五)——MySQL必备命令
今天跟大家分享一下MySQL从连接到具体操作的一系列常用命令.可能有的人觉得现在有很多可视化的工具,没必要再学习那些具体的命令了,但是我不这么认为,不可否认那些工具的确让我们的工作更加方便快捷,但是如 ...
- python(59):yield 函数
可迭代对象: 当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象: >>> mylist = [1, 2, 3] >>> for i in myli ...
- python中redis查看剩余过期时间以及用正则通配符批量删除key的方法
# -*- coding: utf-8 -*- import redis import datetime ''' # 1. redis设置过期时间的两种方式 expire函数设置过期时间为10秒.10 ...
- 开源中国(oschina.net)能给我一个交代吗?
一年前准备把goolge上面diocp项目移动到开源中国上面,当时觉得开源中国的的速度还不错,都叫开源中国了,觉得应该稳定. 后来把今年开源mybean项目也放在上面了,还有一些小的项目都放在上面,就 ...
- scala连接数据库
scala连接数据库 使用JDBC即可: 在sbt中添加对应依赖 libraryDependencies ++= Seq( "mysql" % "mysql-connec ...
- Python字符串、时间戳、datetime时间相关转换
总结的时间转换函数 # datetime时间转为字符串 def Changestr(datetime1): str1 = datetime1.strftime('%Y-%m-%d %H:%M:%S') ...
- lsblk命令
lsblk命令用于列出所有可用块设备的信息,而且还能显示他们之间的依赖关系,但是它不会列出RAM盘的信息.块设备有硬盘,闪存盘,cd-ROM等等.lsblk命令包含在util-linux-ng包中,现 ...
- linux清理Java环境
1.清理Java环境rm -f /usr/bin/javarm -f /etc/alternatives/java rm -f /usr/bin/javacrm -f /etc/alternative ...
- eclipse中git插件使用
1,首先看下文件的几个工作区:Unstaged Changes(本地工作空间),Staged Changes(Add to Index操作之后代码存放的地方),Local Repository(本地仓 ...