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

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. Azure产品目录

    计算 Linux 虚拟机:为 Ubuntu.Red Hat 等预配虚拟机 Windows 虚拟机 为 SQL Server.SharePoint 等预配虚拟机 应用服务 快速创建适用于 Web 和移动 ...

  2. Linux/CentOS关闭图形界面(X-window)和启用图形界面命令

    1.在图像界面关闭x window:1.1 shell中运行 init 3  进入文本模式,同时会关闭相关的服务(Xserver 肯定关闭)1.2 Alt+Ctrl+F1~F6到字符界面,root登陆 ...

  3. 在javascript中获取一个对象内属性的个数

    var foo = {a1:'1',a2:'2',a3:'3'}; //获得对象所有属性的数组 Object.getOwnPropertyNames(foo); > [ 'a1', 'a2', ...

  4. matlab问题集总

    每次更新一点,慢慢增加 nargin nargin是用来判断输入变量个数的函数,这样就可以针对不同的情况执行不同的功能.通常可以用他来设定一些默认值,如下面的函数. 例子,函数test1的功能是输出a ...

  5. javascript基础拾遗(十三)

    1.jQuery的特点 jQuery是目前非常流行的javascript库,理念是"Write Less,Do More" 1)消除浏览器差异 2)简洁的操作DOM方法 3)轻松实 ...

  6. python--笨方法学python 习题52

    笨方法学python是一本不错的python入门书籍.书的最后一节是一个web版的游戏程序,以下是程序代码: 1.项目的目录结构如下所示:skeleton\ app.py map.py templat ...

  7. 每日英语:Foreign Tourists Skip Beijing

    Overseas tourists continued to shun Beijing through 2013. shun:避开,避免,回避 Amid rising pollution and a ...

  8. Android 编程下通过 Theme 和 Style 避免 APP 启动闪黑屏

    之前在做 APP 的时候不太关注这个问题,因为自己在使用其他 APP 的时候也会在应用启动的初始有一个黑屏闪过后才会出现应用的欢迎页.直到最近开发过程中发现自己在欢迎页启动的线程由于请求和处理的数据量 ...

  9. WebSocket通信协议 API简介

    WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如 Chrome,Safari,Firefox,Opera,IE等等,对该协议支持最早的应该是chrome,从ch ...

  10. form的验证包括手机号邮箱等等

    $(function(){    var checkedByVerifyCode = false;    var checkMobieCode = false;    var checkedMobil ...