Binding用于数据有效性校验的是ValidationRules属性,ValidationRules的类型是Collection<ValidationRule>,可以为Binding设置多个数据校验条件,每个条件是一个ValidationRule类型对象。
ValidationRule是一个抽象类,在使用的时候我们需要创建它的派生类并实现它的Validate方法。
Validate方法的返回值是一个ValidationResult类型的对象,如果校验通过,就把ValidationResult对象的IsValid属性设置为true,反之,需要把IsValid属性设置为false并未其ErrorContent属性设置一个合适的消息内容。
下面我们在UI上绘制一个TextBox和Slider,然后再C#代码里使用Binding把他们关联起来,以Slider为源,TextBox为目标,Slider的取值范围是0到100,XAML代码如下:
<TextBox x:Name="txt_Value" Margin="10"></TextBox> <Slider x:Name="slider" Maximum="100" Minimum="0"></Slider>
为进行校验,准备一个校验类,代码如下:
public class RangeValidationRule:ValidationRule { public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { double d = 0; if(double.TryParse(value.ToString(),out d)) { if(d>=0 && d<=100) { return new ValidationResult(true, null); } } return new ValidationResult(false, "Validation Error"); } }
然后再窗体的构造函数里建立Binding,代码如下:
Binding b = new Binding("Value"){Source=this.slider}; b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; var r = new RangeValidationRule(); b.ValidationRules.Add(r); this.txt_Value.SetBinding(TextBox.TextProperty, b);
运行程序就会发现,当输入0到100之间的数值时程序正常显示,但输入这个区间之外的数值或输入不能被解析的值时,TextBox会显示红色的边框,表示值是错误的,不能把它传递个Source。
Binding进行校验时默认是认为来自Source的数据总是正确的,只有来自Target的数据才有可能有问题,即只在Target数据被外部方法更新时进行校验,而Source数据更新Target时是不会进行校验的。如果想改变这种默认行为就需要将属性ValidatesOnTargetUpdated设置为true。
如果想显示ValidationResult的ErrorContent,可以使用路由事件。首先将Binding的NotifyOnValidationError属性设置为true,这样当数据校验失败时Binding就会发出报警信号,这个信号会在以Binding对象的Target为起点的UI元素树上传播。信号每到达一个结点,如果这个结点上设置有针对这种信号的侦听器(事件处理器),那么这个侦听器就会被触发用以处理这个信号。
建立Binding的代码如下:
Binding b = new Binding("Value"){Source=this.slider}; b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; var r = new RangeValidationRule(); r.ValidatesOnTargetUpdated = true; b.ValidationRules.Add(r); b.NotifyOnValidationError = true; this.txt_Value.SetBinding(TextBox.TextProperty, b); this.txt_Value.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));
事件处理代码如下:
private void ValidationError(object sender, RoutedEventArgs e) { if(Validation.GetErrors(this.txt_Value).Count>0) { this.txt_Value.ToolTip = Validation.GetErrors(this.txt_Value)[0].ErrorContent.ToString(); } }