WPF-9: Binding -4

来自《深入浅出WPF》(刘铁猛)读书笔记

Binding的数据校验

使用属性ValidationRules,类型为Collection<validationRule>。ValidationRule类是一个抽象类,在使用的时候我们需要创建它的派生类并实现它的Validate方法。Validate方法的返回值是ValidationResult类型对象,如果校验通过,就把ValidationResult对象的IsValid属性设为true,反之,需要把IsValid属性设为false并为其ErrorContent属性设置一个合适的消息内容(一般是个字符串)。

下面实例是在UI上绘制一个textBox和一个Slider,以Slider为源,TextBox为目标。Slider的取值范围【0,100】。

为了进行校验,需要准备一个ValidationRule的派生类:

public class RangeValidationRule:ValidationRule
{
    //need commit Validate method
    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 Failed");
     }
}

然后在窗体的构造器里这样建立Binding:

public Window1()
{
    InitializeComponent();
    Binding binding=new Binding("Value"){Source=this.slider1};
    binding.UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged;
    RangeValidationRule rvr=new RangeValidationRule();
    binding.ValidationRules.Add(rvr);
    this.textBox1.SetBinding(TextBox.TextProperty,binding);
}
Binding进行校验时的默认行为是认为来自Source的数据总是正确的,只有来自Target的数据(因为Target多为UI控件,所以等价于用户输入的数据)才有可能有问题。只有在Target被外部方法更新时校验数据,而来自Binding的Source数据更新Target时不用进行校验的。如果想改变这种行为,或者说当来自Source的数据也有可能出问题时,我们就需要将校验的ValiatesOnTargetUpdated属性设为true。

如何显示ValidationFailed的消息:

binding.NotifyOnValidationError=true;
...
this.textBox1.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(this.ValidationError));

用于侦听校验错误事件的事件处理器如下:

void ValidationError(object sender,RoutedEventArgs e)
{
    if(Validation.GetErrors(this.textBox1).Count>0) 
    this.textBox1.ToolTip=Validation.GetErrors(this.textBox1)[0].ErrorContent.ToString();
}

程序运行时如果校验失败,TextBox的ToolTip就会提示用户。


Binding的数据转换

上例中Slider的Value(double)与TextBox(string)建立关联,需要做数据转换。

简单的类型转换,WPF类库可以帮我们做完,其他的需要手动写Converter,方法是创建一个类并让这个类实现IValueConverter接口。

public interface IValueConveter
{
    object Convert(object value,Type targetType,object parameter,CultureInfo culture);
    object ConvertBack(object value,Type targetType,object parameter,CultureInfo culture);
}

Binding对象的Mode属性会影响到这两个方法的调用。如果Mode为TwoWay或Default,那两个方法都有可能被调用;如果为OneWay或Default行为,则只有Convert被调用。


MultiBinding

有时候UI需要显示的信息由不止一个数据来源决定,这就组要MultiBinding,即多路Binding。

凡是能使用Binding对象的场合都能使用MultiBinding,它具有一个名为Bindings的属性,其类型是Collection<BindingBase>,通过这个属性MultiBinding把一组Binding对象集合起来,处在这个集合中的Binding对象可以拥有自己的数据校验与转换机制,他们汇聚起来的数据将共同决定传往MultiBinding目标的数据。

MultiBinding对于添加子级bindingde1顺序是敏感的,因为这个顺序决定了汇聚到Converter里数据的顺序;Converter实现的是IMultiValueConverter接口。


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325659802&siteId=291194637