依赖属性详解
简介:当你开始用WPF编程的时候,很快就会碰到“依赖属性 ”。它们和一般的.Net属性看起来很相似,但简单概念之后则是更复杂和更强大。 主要的区别在于:平常的.NET属性的值直接读取 于类的一个私有属性,而依赖属性的值则是通过调用继承自DependencyObject的GetValue()方法动态赋值 的。 当你给一个依赖属性赋值时,它不是存储在对象的字段 中,而是在存储在基类DependencyObject提供的一个键-值配对的字典 中。一条记录中的键(Key)就是该属性的名称,而值(Value)则是想要设置的值。 依赖属性的优点:
值访问策略每次访问一个依赖属性,它内部会按照下列的顺序由高到底处理该值。它首先确认自身的值是否可用,如果不可用,则会触发一个自定义的样式触发器……继续直到它找到一个值。最后默认值经常是可用的。
背后的秘密每一个WPF控件注册了一系列的依赖属性在静态的DependencyProperty类中。他们由一个键值(对每个类都是唯一的)和包含默认值和回调函数的原数据组成。 所有要使用依赖属性(DependecyProperties)的类型都必须由DependencyObject来驱动。这个基类定义了一个键值字典来存储依赖属性的所有值。记录中的键则是依赖属性主要申明的。 当你通过.Net属性包装器访问依赖属性的时候,它在内部会调用一个方法GetValue(DependencyProperty)来访问值。下图详细的解释了该方法使用的值解决策略。 如果当前值是可用的,那么就直接从字典(Dictionary)里读出该值。如果没有值被设定,它将上升到整个逻辑树,寻找一个可继承的值。如果没有找到可继承的值,它将被设置为在属性原数据中定义好的默认值。下面的序列有点简化,但它显示了主要的思想。
创建依赖属性创建一个依赖属性,需添加一个DepdencyProperty类型的静态字段,并调用DependencyProperty.Register()来创建一个依赖属性的实例。依赖属性一般需要以…Property结尾。这样符合PWF的命名规范。 为了使依赖属性像一般的.Net属性一样被访问,则需要添加一个属性包装器。该包装器除了通过继承自DependencyObject的GetValue()和SetValue()方法,以DependencyProperty作为键值来设置和读取它的值外不做任何事情。 强调:不要在这些属性中添加任何逻辑,因为它们仅仅当在代码中赋值的时候才被调用。而在XAML中可直接调用SetValue方法设定属性 。 如果你使用的是Visual Studio,你可以输入propdp在敲两次tab键来自动创建一个依赖属性。 代码1 // Dependency Property 每一个依赖属性都提供为修改通知,值的强制转换和验证提供了一些回调函数,这些函数须在依赖属性中注册。 new FrameworkPropertyMetadata( DateTime.Now, 值的修改回调: 修改回调是一个静态方法,任何时候,只要TimeProperty的值改变了,它都会被调用。新的值会在EventArgs参数传输,此次改变的对象则在source里传输。 代码private static void OnCurrentTimePropertyChanged(DependencyObject source, 值的限制回调: 限制制回调函数允许调整一个值,如果出界,将会抛出一个异常。一个好的例子就是在进度条中设置一个最大上限值或者最小下限值。这种情况下我们可以限定值在允许的范围内。下面的例子我们排出了已经过去了的时间。 private static object OnCoerceTimeProperty( DependencyObject sender, object data )
值的验证回调:验证回调用来检验要设置的值是否有效。如果返回无效的(False),则抛出一个ArgmentException的异常。我们例子的要求是数值必须是DataTime的实例. private static bool OnValidateTimeProperty( object data) 只读的依赖属性: 一些WPF控件的依赖属性是只读的。它们经常用于报告控件的状态, 像IsMouSEOver属性。 为它提供赋值是没有意思的。 或许你会问自己,为什么不使用一般的.Net属性?一个重要的原因就是一般的.Net属性不能设置触发器(Trigger)。 创建一个只读的属性跟创建一个平常的属性一样。仅仅用DependencyProperty.RegisterReadonly()替换了 DependencyProperty()。它将返回一个DependencyPropertyKey。这个键值可以保存在类的私有或者保护的静态只读字 段里。该键值在类的内部提供了一个赋值的入口,便可以像一般属性一样使用了。 紧接着第二件事就是注册一个公开的依赖属性指向DependencyPropertyKey.DependencyProperty。这个属性对外部的访问便是只读的。 代码// Register the private key to set the value (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |