深入浅出WPF 第二部分(10)

本文介绍WPF中Binding的数据校验与类型转换方法。详细解释了如何利用ValidationRule进行数据有效性检查,并展示了如何创建自定义验证规则。此外,还介绍了如何通过设置属性来响应数据校验失败的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6.4 Binding对数据的转换与校验

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

6.4.1 Binding的数据校验

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

using System.Windows.Controls;

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

    <Grid x:Name="g1" Background="Orange" Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBox x:Name="textBox1" Margin="5" Grid.Row="0"/>
        <Slider x:Name="slider1" Margin="6" Maximum="110" Grid.Row="1"/>
    </Grid>

Binding只在Target被外部方法更新时检索数据,或者说当来自Source的数据也有可能出现问题时,我们就需要检索条件的ValidatesOnTargetUpdated属性设为true。

首先创建Binding时要把Binding对象的NotifyOnValidationError属性设为true,这样当数据校验失败的时候 binding会像报警器一样发出一个信号,这个信号会以Binding对象的Target为起点在UI元素树上传播。信号每到达一点,如果这个节点上设置有对这种信号的侦听器(事件处理器),那么这个侦听器就会被触发用以处理这个信号。信号处理完后,程序员还可以选择让信号继续向下传播还是就此终止——这就是路由事件,信号在UI元素树上的传递过程称为路由(Route)。

        public MainWindow()
        {
            InitializeComponent();

            var source=new Binding("Value") 
            { 
                ElementName = "slider1", 
                UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged
            };

            var rar = new RangeValidationRule();

            rar.ValidatesOnTargetUpdated = true; //1#
            
            source.ValidationRules.Add(rar);

            source.NotifyOnValidationError = true; //2#

            textBox1.SetBinding(TextBox.TextProperty, source);

                          //5#路由事件  
            this.textBox1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError)); //3# 加载路由委托
        }

        void ValidationError(object sender, RoutedEventArgs e)
        {
            foreach (var error in Validation.GetErrors(this.textBox1)) //4#
                this.textBox1.ToolTip = error.ErrorContent.ToString();
        }
    }


XAML实现:


    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            listBox1.ItemsSource = LoadData().DefaultView;
        }

        public DataTable LoadData()
        {
            DataTable dt = new DataTable();
            string connStr = "Data Source=.;Initial Catalog=mydb;Integrated Security=True";
            SqlCommand sqlCmd = new SqlCommand("select * from dbo.Person", new SqlConnection(connStr));
            SqlDataAdapter adapter = new SqlDataAdapter(sqlCmd);
            adapter.Fill(dt);
            return dt;
        }
    }

    public class NameValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            string name = value as string;

            if (string.IsNullOrEmpty(name) || name.Length > 10)
                return new ValidationResult(false, "bad name...");
            else
                return new ValidationResult(true, null);
        }
    }

            <ListBox x:Name="listBox1">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Label Content="{Binding Path=ID}" Width="40"/>
                            <TextBox Width="100">
                                <TextBox.Text>
                                    <Binding>
                                        <Binding.Path>Name</Binding.Path>
                                        <Binding.NotifyOnValidationError>True</Binding.NotifyOnValidationError>
                                        <Binding.ValidationRules>
                                            <proj:NameValidationRule ValidatesOnTargetUpdated="True"/>
                                        </Binding.ValidationRules>
                                    </Binding>
                                </TextBox.Text>
                            </TextBox>
                            <TextBox Text="{Binding Path=Age}" Width="100"/>
                            <TextBox Text="{Binding Path=Comment}" Width="120"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

XAML实现:

        <StackPanel>
            <TextBox x:Name="textBox2"  Margin="5"/>
            <TextBox x:Name="textBox1" Margin="5"/>
            <TextBox x:Name="textBox3" Margin="5">
                <TextBox.Text>
                    <Binding ElementName="textBox1" UpdateSourceTrigger="PropertyChanged">
                        <Binding.Path>.Text</Binding.Path>
                        <Binding.NotifyOnValidationError>True</Binding.NotifyOnValidationError>
                        <Binding.ValidationRules>
                            <sys:ValidateLengthError ValidatesOnTargetUpdated="True"/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>    
            </TextBox>
        </StackPanel>

        public MainWindow()
        {
            InitializeComponent();

            textBox1.TextChanged += new TextChangedEventHandler(this.ValidationError);
        }

        void ValidationError(object sender, RoutedEventArgs e)
        {
            this.textBox2.Text = "";
            foreach (var error in Validation.GetErrors(this.textBox3))
            {
                this.textBox1.ToolTip = error.ErrorContent.ToString();
                this.textBox2.Text = error.ErrorContent.ToString();
            }
        }

    class ValidateLengthError : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (value is string)
            {
                string str = value as string;
                if (str.Length > 5)
                    return new ValidationResult(false, "more than 5");
                else
                    return new ValidationResult(true, null);
            }
            else
                return new ValidationResult(false, "bad type");
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值