WPF学习笔记依赖属性

属性和依赖属性

  属性是我们很熟悉的,封装类的字段,表示类的状态用,可以被类或结构使用。常见的属性如下:

public class Student
{
    private String _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

在面向对象中,属性大量的存在供程序员们使用,但是基本绝大多数都会保持默认值,没有被修改,会造成极大的浪费。对系统的开销也不小。

  因此,在WPF中,它提供了可用于扩展CLR属性的服务,来替换原来的.NET属性。叫做依赖属性,依赖属性在每个类实例中使用一个字典型的成员变量来存放那些用户显式设置的属性。而大多数属性用到的默认值存放在依赖属性的静态成员变量中,它具有更高效的保存机制,大大的提高了效率。

依赖属性的注册

  因为DependencyProperty类没有公有的构造函数,所以不能直接实例化,只能用静态的DependencyProperty.Register()方法创建DependencyProperty实例。

看到别人写的注册依赖属性的步骤拿来学习下:

第一步: 让所在类型继承自 DependencyObject基类,在WPF中,我们仔细观察框架的类图结构,你会发现几乎所有的 WPF 控件都间接继承自DependencyObject类型。 
第二步:使用 public static 声明一个 DependencyProperty的变量,该变量才是真正的依赖属性 ,看源码就知道这里其实用了简单的单例模式的原理进行了封装(构造函数私有),只暴露Register方法给外部调用。 
第三步:在静态构造函数中完成依赖属性的元数据注册,并获取对象引用,看代码就知道是把刚才声明的依赖属性放入到一个类似于容器的地方,没有讲实现原理之前,请容许我先这么陈述。 
第四步:在前面的三步中,我们完成了一个依赖属性的注册,那么我们怎样才能对这个依赖属性进行读写呢?答案就是提供一个依赖属性的实例化包装属性,通过这个属性来实现具体的读写操作

下面先注册一个依赖属性,同时添加一个属性包装器:

        public class SampleDP : DependencyObject {
            public static readonly DependencyProperty SampleProperty = DependencyProperty.Register(
            "Sample", typeof(string), typeof(SampleDP), null);
            public string Sample {
                get { return (string)GetValue(SampleProperty); }
                set { SetValue(SampleProperty, value); }
            }
        }

然后就能够使用这个依赖属性:

            SampleDP dp=new SampleDP();
            dp.Sample = "Sample";

Register函数有很多重载,一个最全的形式如下:

public static DependencyProperty Register(string name, Type propertyType, Type ownerType, 
           PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback);

在上面的注册中,需要提供几个要素:第一个是属性名;第二个是属性的数据类型;第三个是注册此依赖属性的类;第四个是具有附加属性设置的PropretyMetadata对象,是可选的。

第五个是验证属性的回调函数,也是可选的。

依赖属性的动态值识别(优先级)

  WPF决定一个属性值的四步骤过程:

(1)确定基本值。这些基本值可以通过一下来考虑(从低到高):1.默认值2.继承而来的值3.来自主题样式的值4.来自项目样式的值5.本地址

(2)如果属性是使用表达式设置的,则对该表达式进行求值。当前WPF支持两类表达式:数据绑定和资源。

(3)如果该属性是动画,应用该动画。

(4)运行CoerceValueCallback回调函数修正属性值。如果我们在FrameworkPropertyMetadata中传入了CoerceValueCallback,WPF属性系统会回调我们传入的的delagate,进行数据的强制赋值。在属性赋值过程中,Coerce拥有最高的优先级,这个优先级要大于动画的优先级别。

共享的依赖属性

  一些类会共享同一个依赖属性,尽管这些类是不同的继承层次。例如,TextBlock.FontFamily属性和Control.FontFamily属性指向同一个静态依赖属性,该属性实际上是在Tex-tElement类中第一的TextElement.FontFamilyProperty依赖属性。TextElement只是注册该属性,而TextBlock和Control是调用方法来重用该属性:

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

这个重用依赖属性在样式里面会有着一些奇异的效果。

附加属性

  就像前面所说的布局模板中可以看到附加属性的最常见的例子,如Grid类中定义的Row和Column就是附加属性。在前面的注册中是使用DependencyProperty.Register来注册DP的,而在附加属性中,使用的是DP中的DependencyProperty.RegisterAttached方法来注册。其他的和注册依赖属性是差不多的。都可以提供一个DependencyProperty对象和ValidateValueCallback。附加属性不是使用.NET属性包装器,而是使用的两个静态方法获取属性值,这两个方法使用的就是我们所熟悉的SetValue()和GetValue()方法。

属性验证

这个由于本人是新手还在学习所以以后再写~

  

原文地址:https://www.cnblogs.com/socialdk/p/2520429.html