十. PropertyMetadata测试代码
public static DependencyProperty Register(string name,
Type propertyType,175);">Type ownerType,175);">PropertyMetadata typeMetadata,175);">ValidateValueCallback validateValueCallback);
第一个参数是该依赖属性的名字,第二个参数是依赖属性的类型,第三个参数是该依赖属性的所有者的类型,第五个参数就是一个验证值的回调委托,那么最使我们感兴趣的还是这个可爱的
PropertyMetadata ,也就是我们接下来要讲的元数据。 提到WPF属性元数据,大家可能第一想到的是刚才的PropertyMetadata,那么这个类到底是怎样的呢?我们应该怎样使用它呢?首先我们看它的构造函数(我们选参数最多的来讲):
public PropertyMetadata(object defaultValue,
PropertyChangedCallback propertyChangedCallback,
CoerceValueCallback coerceValueCallback);
事实上,除了PropertyMetadata以外,常见的还有 FrameworkPropertyMetadata,UIPropertyMetadata。他们的继承关系是F->U->P。其中以 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,所以最重要的还是我们定义的这些方法,通过他们传入委托才能起到真正的作用。
在写其他测试用例之前,我们先来创建两个类,第一个类TestDepObj,内部注册了四个依赖属性,前三个没有元数据操作,也就是没有显示声 明并构造元数据类,第四个添加了一个元数据类,这个元数据类包含了默认值、值改变回调委托、强制值回调委托。第二个类TestSubclass继承自 TestDepObj。
1: class TestDepObj : DependencyObject
2: {
3: public static readonly DependencyProperty TestProp1 = DependencyProperty.Register("property1",typeof(string),255);">typeof(TestDepObj));
4: readonly DependencyProperty TestProp2 = DependencyProperty.Register("property2",255);">typeof(TestDepObj));
5: readonly DependencyProperty TestProp3 = DependencyProperty.Register("property3",255);">typeof(TestDepObj));
6:
7: readonly DependencyProperty TestProp4 = DependencyProperty.Register("property4",255);">typeof(TestDepObj),255);">new PropertyMetadata("default",changed,coerce));
8:
9: void changed(DependencyObject d,DependencyPropertyChangedEventArgs e) { }
10: object coerce(DependencyObject d,255);">object baseValue) { return baseValue; }
11: }
12:
13: class TestSubclass : TestDepObj
14: {
15: }
大家看到我们在创建PropertyMetadata的时候对某些功能并没有实现,这里我们就通过子类来具体实现,MONO的这种做法想沿袭微 软PropertyMetadata、FrameworkPropertyMetadata和UIPropertyMetadata的做法,但是个人觉得 它实现得并不是太好,很多地方感觉很别扭。
//首先我们自定义一个元数据类,继承自我们刚创建的PropertyMetadata类
2: class PropertyMetadataPoker : PropertyMetadata
3: {
4:
5: bool BaseIsSealed
6: {
7: get { return base.IsSealed; }
8: }
9:
10: void CallApply()
11: {
12: OnApply(TestDepObj.TestProp1,255);">typeof(TestDepObj));
13: }
14:
15: void CallMerge(PropertyMetadata baseMetadata,DependencyProperty dp)
16: {
17: Merge(baseMetadata,dp);
18: }
19:
20: protected override void Merge(PropertyMetadata baseMetadata,DependencyProperty dp)
21: {
22: Console.WriteLine(Environment.StackTrace);
23: base.Merge(baseMetadata,dp);
24: }
25:
26: void OnApply(DependencyProperty dp,Type targetType)
27: {
28: //
29: base.OnApply(dp,targetType);
30: Console.WriteLine("IsSealed in OnApply? {0}",IsSealed);
31: Console.WriteLine(Environment.StackTrace);
32: }
33: }