十一. 依赖属性元数据
前面我们看到一个依赖属性的注册最全的形式是下面这样子的:
public static DependencyProperty Register(string name,
Type propertyType,
Type ownerType,
PropertyMetadata typeMetadata,
ValidateValueCallback validateValueCallback);
第一个参数是该依赖属性的名字,第二个参数是依赖属性的类型,第三个参数是该依赖属性的所有者的类 型,第五个参数就是一个验证值的回调委托,那么最使我们感兴趣的还是这个可爱的 PropertyMetadata ,也 就是我们接下来要讲的元数据。 提到WPF属性元数据,大家可能第一想到的是刚才的PropertyMetadata,那么 这个类到底是怎样的呢?我们应该怎样使用它呢?首先我们看它的构造函数(我们选参数最多的来讲):
public PropertyMetadata(object defaultValue,
PropertyChangedCallback propertyChangedCallback,
CoerceValueCallback coerceValueCallback);
其中的第一个参数是默认值,最后两个分别是PropertyChanged(变化通知)以及Coerce(强制)的两个委 托变量,我们在实例化的时候,只需要把这两个委托变量关联到具体的方法上即可。
事实上,除了PropertyMetadata以外,常见的还有 FrameworkPropertyMetadata,UIPropertyMetadata。 他们的继承关系是F->U->P。其中以 FrameworkPropertyMetadata参数最多,亦最为复杂。
FrameworkPropertyMetadata的构造函数提供了很多重载,我们挑选最为复杂的重载来看它到底有哪些参数 以及提供了哪些功能:
public FrameworkPropertyMetadata(object defaultValue,
FrameworkPropertyMetadataOptions flags,
PropertyChangedCallback propertyChangedCallback,
CoerceValueCallback coerceValueCallback,
bool isAnimationProhibited,
UpdateSourceTrigger defaultUpdateSourceTrigger);
其中第一个参数是默认值,最后两个参数分别是是否允许动画,以及绑定时更新的策略(在Binding当中相 信大家并不陌生),这个不详细解释了。重点看一下里第三、四两个参数,两个 CallBack的委托。结合前面 Register的时候提到的ValidateValueCallback共组成三大”金刚“,这三个Callback 分别代表Validate(验 证),PropertyChanged(变化通知)以及Coerce(强制)。当然,作为 Metadata, FrameworkPropertyMetadata只是储存了该依赖属性的策略信息,WPF属性系统会根据这些信息来提供功能并在 适当的时机回调传入的delegate,所以最重要的还是我们定义的这些方法,通过他们传入委托才能起到真正的 作用。
上面讲了元数据暴露给我们的构造函数,其实在其内部还提供了两个方法,这个在做自定义控件的时候, 也很值得注意:
protected virtual void Merge(PropertyMetadata baseMetadata, DependencyProperty dp)
{
// 实现元数据继承之间的合并
}
protected virtual void OnApply(DependencyProperty dependencyProperty, Type targetType)
{
// 当元数据被这个属性应用,OnApply就会被触发,在此时元数据也将被密封起来。
}
前面讲了这么多,那么我们现在就来看看依赖属性回调、验证及强制值到底是怎么使用的呢?大家千万要 坚持住,后面内容更加精彩!
十二. 依赖属性回调、验证及强制值
我们通过下面的这幅图,简单介绍一下WPF属性系统对依赖属性操作的基本步骤: