标签:静态方法 typeof pyc 依赖 pen 内容 适应 更改 logs
原文:【WPF学习】第十二章 属性验证
在定义任何类型的属性时,都需要面对错误设置属性的可能性。对于传统的.NET属性,可尝试在属性设置器中捕获这类问题。但对于依赖项属性而言,这种方法不合适,因为可能通过WPF属性系统使用SetValue()方法直接设置属性。
作为代替,WPF提供了两种方法来阻止非法值:
下面是当应用程序试图设置依赖项属性时,所有这些内容的作用过程:
(1)首先,CoerceValueCallback方法有机会修改提供的值(通常,使提供的值和其他属性相容),或者返回DependencyProperty.UnsetValue,这会完全拒绝修改。
(2)接下来激活ValidateValueCallback方法。该方法返回true以接受一个值作为合法值,或者返回false拒绝值。与CoerceValueCallback方法不同,ValidateValueCallback方法不能访问设置属性的实际对象,这意味着你不能检查其他属性值。
(3)最后,如果前两个阶段都获得成功,就会触发PropertyChangedCallback方法。此时,如果希望为其他类提供通知,可以引发更改事件。
一、验证回调
正如前面所看到的,DependencyProperty.Register()方法接受可选的验证回调函数:
static FrameworkElement(){ FrameworkPropertyMetadata metadata=new FrameworkPropertyMetadata(new Thickness(),FrameworkPropertyMetadataOptions.AffectsMeasure); MarginProperty=DependencyProperty.Register("Margin",typeof(Thickness),typeof(FrameworkElement),metadata,new ValidateValueCallback(FrameworkElement.IsMarginValid)); .... }
可使用这个回调函数验证,验证通常应被添加到属性过程的设置部分。提供的回调函数必须指向一个接受对象参数并返回Boolean值得方法。返回true以接受对象是合法的,返回false拒绝对象。
对FrameworkElement.Margin属性的验证十分枯燥乏味,因为它依赖于内部的Thickness.IsValid()方法。该方法确保当前使用的Thickness对象(表示边距)是合法的。例如,可能构造了一个完全可以接受的Thickness对象(却不适于设置边距)。一个例子是Thickness对象使用了负值。如果提供的Thickness对象对于边距时是不合法的。IsMarginValid方法将返回false:
public static bool IsMarginValid(object value) { Thickness thickness1=(Thickness)value; return thickness1.IsValid(true,false,true,false); }
对于验证回调函数有一个限制:它们必须是静态方法而且无权访问正在被验证的对象。所有能够获得的信息只有刚刚应用的数值。尽管这样更便于重用属性,但可能无法创建考虑其他属性的验证例程。典型的例子是具有Maximum和Minimum属性的元素。显然,为Maximum属性设置的值不能小于为Minimum属性设置的值。但是,不能使用验证回调函数来实施这一逻辑,因为一次之恩你访问一个属性。
二、强制回调
通过FrameworkPropertyMetadata对象使用CoerceValueCallback回调函数。下面是示例:
FrameworkPropertyMetadata metadata=new FrameworkPropertyMetadata(new Thickness(),FrameworkPropertyMetadataOptions.AffectsMeasure); metadata.CoerceValueCallback=new CoerceValueCallback(CoerceMaximum); DependencyProperty.Register("Maxium",typeof(double),typeof(RangeBase),metadata);
可以通过CoerceValueCallback回调函数处理相互关联的属性。例如,ScrollBar控件提供了Maximum、Minimum和Value属性,这些属性都继承自RangeBase类。保持对这些属性进行调整的一种方法是使用属性强制。
例如,当设置Maximum属性时,必须使用强制以确保不能小于Minimum属性的值:
private static object CoerceMaximum(DependencyObject d,object value) { RangeBase base1=(RangeBase)d; if((double)value)<base1.Minimum) { return base1.Minimum; } return value; }
换句话说,如果应用于Maximum属性的值小于Minimum属性的值,就用Minimum属性的值设置Maximum属性。注意,CoerceValueCallback传递两个参数——准备使用的数值和该数值将要应用到得对象。
当设置Value属性时,会发生类似的强制过程。对Value属性进行强制,确保不会超出由Minimum和Maximum属性定义的范围,使用下面的代码:
internal static object ConstrainToRange(DependencyObject d,object value) { double newValue=(double)value; RangeBase base1=(RangeBase)d; double minimum=base1.Minimum; if(newValue<minimum) { return minimum; } double maximum=bas1.Maximum; if(newValue>maximum) { return maximum; } return newValue; }
Minimum属性根本不使用值强制。相反,一旦值发生变化,就触发PropertyChangedCallback,然后通过手动触发Maximum和Value属性的强制过程,使它们适应Minimum属性值得变化:
private static void OnMinimumChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { RangeBase base1=(RangeBase)d; ... base1.CoerceValue(RangeBase.MaximumProperty); base1.CoerceValue(RangeBase.ValueProperty); }
类似地,一旦设置或强制Maximum属性的值,那么也会手动强制Value属性以适应Maximum属性值得变化:
private static void OnMaximumChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { RangeBase base1=(RangeBase)d; ... base1.CoerceValue(RangeBase.ValueProperty); base1.OnMaximumChanged((double)e.OldValue,(double)e.NewValue); }
如果设置的值相互冲突,最终结果是Minimum属性具有优先权,其次是Maximum属性(并且可能会被Minimum属性强制),最后是Value属性(并且可能会被Maximum和Minimum属性强制)。
标签:静态方法 typeof pyc 依赖 pen 内容 适应 更改 logs
原文地址:https://www.cnblogs.com/lonelyxmas/p/12285949.html