第4章 依赖属性(2)——自定义依赖属性

来源:互联网 发布:易语言js教程 编辑:程序博客网 时间:2024/06/07 01:22

一、定义依赖属性

相对于创建依赖属性,大多数情况下只是使用它们。但是,仍然有许多原因需要创建自己的依赖属性。例如:

(1)在设计自定义的WPF元素时,定义依赖属性肯定是关键部分。

(2)当希望为原本不支持数据绑定、动画或其他WPF功能的部分代码添加这些功能时,也需要创建依赖属性。

注意:只能为依赖对象(直接或间接继承自DependencyObject的类)添加依赖属性。幸运的是,WPF基础结构的关键部分中的大部分都直接或间接继承自DependencyObject类,最明显的例子就是元素。因为大多数时候都是为元素添加依赖属性,所以第一步定义依赖对象就可以免了。

例如,FrameworkElement类对Margin属性的定义,代码如下:

public class FrameworkElement : UIElement,...{    public static readonly DependencyProperty MarginProperty;}
注意:

(1)使用public static修饰,因为属性信息应该始终保持可用,甚至可能需要在多个类之间共享这些信息。因此必须将DependencyProperty对象定义为与其相关联的类的静态字段。

(2)使用readonly修饰,这意味着只能在FrameworkElement类的静态构造函数中对其进行设置。

(3)根据约定,定义依赖项属性的字段的名称是在普通属性的末尾处加上单词"Property"。

二、注册依赖属性

注册依赖属性一般是在与其关联的类的静态构造函数中进行。代码如下:

static FrameworkElement(){    FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(new Thickness(), FrameworkPropertyMetadataOptions.AffectsMeasure);    MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), typeof(FrameworkElement), metadata, new ValidateValueCallback(FrameworkElement.IsMarginValid));    ……}
DependencyProperty.Register()方法有三个重载,上面代码是参数最多的一个,具体含义如下:

(1)属性名(在该例中为Margin)

(2)属性使用的数据类型(在该例中为Thickness结构)

(3)拥有该属性的类(在该例中为FrameworkElement类)

(4)PropertyMetadata为依赖属性设置附加功能

(5)一个用于验证属性的回调函数

三、封装依赖属性

使用传统的.NET属性封装WPF依赖属性。代码如下:

public Thickness Margin{    get { return (Thickness)GetValue(MarginProperty); }    set { SetValue(MarginProperty, value); }}
四、共享依赖属性
共享依赖属性就是在不同的类之间共享同一个依赖属性。例如,TextBlock.FontFamily属性和Control.FontFamily属性指向同一个静态的依赖属性。该属性实际上是在TextElement类中定义的TextElement.FontFamilyProperty依赖属性。TextElement类的静态构造函数注册该属性,而TextBlock类的静态构造函数只是通过调用DependencyProperty.AddOwner()方法重用该属性:

TextBlock.FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(typeof(TextBlock));

注意:在WPF中重用依赖属性可得到一些奇异的效果,最有名的是样式。例如,如果使用样式自动设置TextBlock.FontFamily属性,样式也会影响Control.FontFamily属性,因为在后台这两个类使用同一个依赖属性。

五、快速创建依赖属性

使用代码片段(code snippet),快捷键为:propdp+两次Tab

0 1
原创粉丝点击