深入浅出WPF之Binding--笔记(2015.03.08)

C#代码:

    RelativeSource rs = new RelativeSource();
    rs.AncestorLevel = 2;
    rs.AncestorType = typeof(DockPanel);
    Binding binding = new Binding("Name") { RelativeSource = rs };
    this.textBox1.SetBinding(TextBox.TextProperty, binding);

或在XAML中设置:

    Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type DockPanel}, AncestorLevel=2}, Path=Name}"

如果TextBox需要关联自身的Name属性,代码是:

    RelativeSource rs = new RelativeSource();
    rs.Mode = RelativeSourceMode.Self;
    Binding binding = new Binding("Name") { RelativeSource = rs };
    this.textBox1.SetBinding(TextBox.TextProperty, binding);

RelativeSource类的Mode属性的类型是RelativeSourceMode枚举,它的取值有:PreviousData、Self、TemplatedParent和FindAncestor。RelativeSource类还有3个静态属性:PreviousData、Self、TemplatedParent,它们的类型是RelativeSource类。实际上这3个静态属性就是创建一个RelativeSource实例、把实例的Mode属性设置为相应的值,然后返回这个实例。之所以准备这3个静态属性是为了在XAML代码里直接获取RelativeSource属性。

    

    Binding用于数据有效性校验的是它的ValidationRules属性,用于数据类型转换的是Converter属性。

    Binding的ValidationRules属性类型是Collection<ValidationRule>,从而可以为每个Binding设置多个数据校验条件,每个条件是一个ValidationRule类型对象。ValidationRule是个抽象类,在使用时需要创建它的派生类并实现它的Validate方法。Validate方法的返回值是ValidationResult类型对象,如果校验通过,就把ValidationResult对象的IsValid属性设为True,反之则把IsValid属性设为false并为其ErrorContent属性设置一合适的消息内容(一般是一个字符串)。

XAML代码:

    <StackPanel>
        <TextBox x:Name="textBox1" Margin="5"/>
        <Slider x:Name="slider1" Minimum="0" Maximum="100" Margin="5"/>
    </StackPanel>

C#代码:

    public class RangeValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            double d = 0d;
            if (double.TryParse(value.ToString(), out d))
                if (d >= 0 && d <= 100)
                    return new ValidationResult(true, null);
            return new ValidationResult(false, "Validation Failed!");
        }
    }

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            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的数据才有可能有问题。Binding只在Target被外部方法更新时校验数据,而来自Binding的Source数据更新Target时不会进行校验。如果想改变这种行为,或者说当来自Source的数据也有可能出问题时,就需要将校验条件的ValidatesOnTargetUpdated属性设为True。

    将上面的XAML中slider改为:

    <Slider x:Name="slider1" Minimum="-10" Maximum="100" Margin="5"/>

同时C#代码:

    RangeValidationRule rvr = new RangeValidationRule();
    rvr.ValidatesOnTargetUpdated = true;    
    binding.ValidationRules.Add(rvr);

要现实错误信息,在创建Binding时要把Binding对象的NotifyOnValidationError属性设为True.这样,当数据校验失败时Binding会发出一个信号,该信号会以Binding对象的Target为起点在UI元素树上传播。信号每到达一个结点,若该结点上设置有对这种信号的侦听器(事件处理器),那么这个侦听器就会被触发用以处理这个信号。信号处理完毕后,还可以选择是让信号继续向下传播还是就此终止――这就是路由事件。信号在UI元素树上的传递过程就称为路由(Route)。

C#代码:

    public class RangeValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            double d = 0d;
            if (double.TryParse(value.ToString(), out d))
                if (d >= 0 && d <= 100)
                    return new ValidationResult(true, null);
            return new ValidationResult(false, "Validation Failed!");
        }
    }

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Binding binding = new Binding("Value") { Source = this.slider1 };
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            RangeValidationRule rvr = new RangeValidationRule();
            rvr.ValidatesOnTargetUpdated = true;   
            binding.ValidationRules.Add(rvr);
            binding.NotifyOnValidationError = true;
            this.textBox1.SetBinding(TextBox.TextProperty, binding);

            this.textBox1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));
        }

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

你可能感兴趣的:(WPF,binding)