三个回调对应依赖属性的验证过程,改变过程和强制转换过程。

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的执行顺序的更多相关文章

  1. WPF的依赖属性

    Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR)属性的功能,这些服务通常统称为 WPF 属性系统.由 WPF 属 ...

  2. WPF的依赖属性和附加属性(用法解释较全)

    转:https://www.cnblogs.com/zhili/p/WPFDependencyProperty.html 一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己 ...

  3. wpf 的依赖属性只能在loaded 事件之后才能取到

    wpf 的依赖属性只能在loaded 事件之后才能取到,在构造函数的  InitializeComponent(); 之后取不到 wpf 的依赖属性只能在loaded 事件之后才能取到,在构造函数的  ...

  4. WPF 中依赖属性的继承(Inherits)

    WPF中依赖属性的值是是可以设置为可继承(Inherits)的,这种模式下,父节点的依赖属性会将其值传递给子节点.例如,数据绑定中经常使用的DataContextProperty: var host ...

  5. WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性

    原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? ...

  6. [转]WPF的依赖属性是怎么节约内存的

    WPF升级了CLR的属性系统,加入了依赖属性和附加属性.依赖属性的使用有很多好处,其中有两点是我认为最为亮眼的: 1)节省内存的开销; 2)属性值可以通过Binding依赖于其它对象上,这就使得我的数 ...

  7. WPF利用依赖属性和命令编写自定义控件

    以实例讲解(大部分讲解在代码中) 1,新建一个WPF项目,添加一个用户控件之后在用户控件里面添加几个控件用作测试, <UserControl x:Class="SelfControlD ...

  8. WPF: 只读依赖属性的介绍与实践

    在设计与开发 WPF 自定义控件时,我们常常为会控件添加一些依赖属性以便于绑定或动画等.事实上,除了能够添加正常的依赖属性外,我们还可以为控件添加只读依赖属性(以下统称"只读属性" ...

  9. WPF 自定义依赖属性

      原博客地址:http://www.cnblogs.com/DebugLZQ/archive/2012/11/30/2796021.html    DependencyObject和Dependen ...

随机推荐

  1. C和指针第13章第4题

    题目:编写一个函数,它用于对一个任何类型的数组进行排序. 算法核心代码sort函数实现 /** 功能说明:sort函数可以对不同类型的数据进行排序 参数: 1.一个指向需要排序的数组的第一个值的指针. ...

  2. /etc/ssh/sshd_config 关建字:AllowUsers root test01

    新加用户,在AllowUsers 新增的用户名,重启sshd后,新增的用户才能登录服务器.

  3. HTML5学习笔记(十一):JavaScript基础

    JavaScript代码可以直接嵌在网页的任何地方,不过通常我们都把JavaScript代码放到<head>中: <head> <script> alert('He ...

  4. mybatis中mapUnderscoreToCamelCase自动驼峰命名转换

    ssm项目中在mybatis配置文件中添加以下配置,可以将数据库中user_name转化成userName与实体类属性对应,如果数据库使用如user_name的命名方式,实体类采用驼峰命名.配置后无需 ...

  5. 解析Delphi 窗口置顶,及非主窗口置顶

    方法一: procedure TForm1.Button2Click(Sender: TObject);begin Form2.Show; Application.NormalizeTopMosts; ...

  6. Delphi实现RGB色环的代码绘制(XE10.2+WIN764)

    相关资料: http://blog.csdn.net/tokimemo/article/details/18702689 http://www.myexception.cn/delphi/215402 ...

  7. velocity单引号与双引号

    (1)最外层是用单引号包围时,双引号直接使用就可以了,两个连续的单引号表示一个单引号:#set($var2 = 'A"B''C') --> $var2 的值为 A"B'C(2 ...

  8. sql优化方法学习和总结

    首先要问自己几个问题: 哪些类型的sql会散发出坏味道? sql优化的基本原理是什么,为什么有的sql快有的慢? sql优化和底层的存储引擎关系大么? 怎么看执行过程? 优化建议 1. 缓存查询,sq ...

  9. am335x Lan8710a 双网口配置

    一. 经过调试, LAN8710A在 am335x 上面需要使用 GMII的模式,设备树 pin mux配置如下: // 下面是工作模式的配置,在睡眠模式下是配成GPIO模式 162 cpsw_def ...

  10. 如何让Composer的autoload支持自定义文件后缀名

    PHP的Composer工具规范了我们对系统各种资源库的加载格式,借助于PHP的自动加载机制,可以很大程度上简化在应用开发过程中的类库文件引用场景.但到目前为止,它有个不是问题的问题,就是文件后缀名只 ...