【WPF】数据验证

引言

     数据验证在任何用户界面程序中都是不可缺少的一部分.在WPF中,数据验证更是和绑定紧紧联系在一起,下面简单介绍MVVM模式下常用的几种验证方式.

错误信息显示

在介绍数据验证之前,有必要介绍一下如何显示错误信息.方式很简单,定义一个样式触发器,将错误信息和 ToolTip绑定,如下:

           <Style TargetType="TextBox">
                <Style.Triggers>
                    <Trigger Property="Validation.HasError" Value="true">
                        <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                    </Trigger>
                </Style.Triggers>
            </Style>

 ValidatesOnExceptions验证规则

ValidatesOnExceptions是WPF预定义的验证规则,它会捕捉任何位置上的异常,包括类型转换异常,属性设置器异常,值转换器异常等.捕捉到异常的时候,输入的边框会变成红色,当然也可以自定义错误的模板(Validation.ErrorTemplate).想要ValidatesOnExceptions生效,将绑定属性中的ValidatesOnExceptions设置为true即可.

PS:无论设置为true或false,类型转换异常总会发生的,也就是总会有红色框.

数据对象中验证

直接在数据对象中编写验证规则是最简单粗暴的方式,如下

        public int Price
        {

            get { return _price; }
            set
            {
                if (Equals(value, _price)) return;

                if (value < 0)
                {

                    throw new ArgumentException("数值不能小于0");

                }
                else
                {
                    _price = value;
                    RaisePropertyChanged(() => Price);
                }
            }
        }

如果小于0,程序不会抛错,文字提示也会显示在ToolTip上,前提是ValidatesOnExceptions=true.

PS:这种方式能如期实现,是因为WPF的Binding 捕捉属性设置中的所有异常.但是,如果是代码设置负数的话,程序直接挂掉.

自定义验证规则

除了WPF预定义的验证规则外,我们还可以自定义验证规则,要继承ValidationRule,编写验证不能大于99的数值,代码如下:

    public class NumberRule : ValidationRule
    {
        public override System.Windows.Controls.ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            int i;
            //  int.TryParse(value.ToString(), out i);
            if (!int.TryParse(value.ToString(), out i))
            {
                return new System.Windows.Controls.ValidationResult(false,
                       "字符串格式不对!");
            }
            if (i > 99)
            {
                return new System.Windows.Controls.ValidationResult(false,
                        "数值不能大于99!");
            }
            else
            {
                return new System.Windows.Controls.ValidationResult(true, null);
            }

        }
    }
       <TextBox  Height="25" Width="100" Margin="208,142,0,0"  VerticalAlignment="Top" HorizontalAlignment="Left" >
            <TextBox.Text>
                <Binding Path="Price" Mode="TwoWay" ValidatesOnDataErrors="True">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule></ExceptionValidationRule>
                        <local:NumberRule></local:NumberRule>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

PS:自定义验证规则总是在ExceptionValidationRule之前进行,所以要在NumberRule加上转换类型的异常处理,不然会有抛错的可能性,当然上面的代码中如果有类型错误变量i总会返回0.

PS:验证的执行顺序:自定义验证规则->值转换器->ExceptionValidationRule->数据对象验证.

 ValidatesOnDataErrors验证规则

正常情况下,上面的几种方式都可以工作得很好,但是属性多达几十个的时候,写起来就不是那么的舒服了.这个时候我们可以通过继承接口IDataErrorInfo来将我们的验证规则统一起来,代码如下:

        public string Error
        { get { return ""; } }

        public string this[string propertyname]
        {
            get
            {
                string result = null;
                if (propertyname == "Price")
                {
                    if (Price >99)
                    {
                        result = "数值不能大于99!!";
                    }
                }
                return result;
            }
        }
Error在WPF中没作用,返回任意都可以.PS:记得把ValidatesOnDataErrors=truePS:验证的执行顺序:自定义验证规则->值转换器->ExceptionValidationRule->数据对象验证->ValidatesOnDataErrors.

进阶 ValidatesOnDataErrors验证规则ValidatesOnDataErrors虽然能统一起来到一个地方,但是还免不了每一个属性单独写一个规则.所以我们需要一个更简便的方式,那就是DataAnnotations+IDataErrorInfo的方式,代码如下:
        private int _price;
        [Range(0, 99, ErrorMessage = "数值要在0到99之间")]
        public int Price
        {

            get { return _price; }
            set
            {
                if (Equals(value, _price)) return;

                if (value < 0)
                {

                    throw new ArgumentException("数值不能小于0");

                }
                else
                {
                    _price = value;
                    RaisePropertyChanged(() => Price);
                }
            }
        }

        public string this[string propertyname]
        {
            get
            {
                var vc = new ValidationContext(this, null, null);
                vc.MemberName = propertyname;
                var res = new List<System.ComponentModel.DataAnnotations.ValidationResult>();

                var result = Validator.TryValidateProperty(this.GetType().GetProperty(propertyname).GetValue(this, null), vc, res);
                if (res.Count > 0)
                {
                    return string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
                }
                return string.Empty;
            }
        }

采用这种方式,开发的时候只需要简单的设置一下特性,就能如期望的显示我们的验证提示了,关于这种方式的详细用法,网上有一篇更好的文章:传送门.

 注意事项

到这里,如果没有什么意外,相信大家都会采用DataAnnotations+IDataErrorInfo的方式,这种方式实现最简单,而且发生在viewmodel上,我们很容易地在保存环节得到所有异常信息,从而阻止保存数据的进行.但是WPF的数据验证中都有个通病,就是发生数据异常的时候,属性实际的值还是上次合法的值,和界面上显示的值有所不同.这个时候如果用户强行保存,我们就发现DataAnnotations+IDataErrorInfo的验证方式竟然通过了!这不符合我们的期望.这种情况我没发现有什么优雅的解决方案,暂时想到的只有在按钮的点击事件中遍历LogicalTreeHelper的输入控件,检查Validation.HasError属性,组合异常信息传给viewmodel,让viewmodel作出处理.其实最为彻底的方式是,封装数字输入控件等各类特定的控件,提高用户体验的同时,也让异常处理更简单.

小结

    本文简单介绍了WPF数据验证的各种方式,而我们基本上都会采用 DataAnnotations+IDataErrorInfo的方式,如果您有更好的方式,请不吝指教,感激不尽!

 
时间: 2024-11-03 03:24:44

【WPF】数据验证的相关文章

WPF数据验证

当填写表单时,需要对填写的内容进行验证,检查数据是否符合要求,比如字符串的长度.日期的格式.数字等.WPF支持自定义验证规则,并提供可视化反馈,以便在输入无效值时向用户发出通知. 下面的示例将演示一个模拟员工信息录入的过程,员工的年龄为大于18的整数,工资为大于2500的数字,如果输入错误,将在文本框的后面显示一个红色的叹号,当鼠标移至错误文本框时,显示提示消息,提示用户正确的输入格式.   数据的验证 可以继承ValidationRule类,重写Validate方法,实现自定义的验证规则 下面

WPF MVVM从入门到精通8:数据验证

原文:WPF MVVM从入门到精通8:数据验证 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 WPF MVVM从入门到精通4:命令和事件 WPF MVVM从入门到精通5:PasswordBox的绑定 WPF MVVM从入门到精通6:RadioButton等一对多控件的绑定 WPF MVVM从入门到精通7:关闭窗口和打开新窗口 WPF MVVM从入门到精通8:数据验证 完整示例代码下载LoginDemo

关于WPF的验证

1.ValidationRule 验证 ValidationRule:是通过ValidationRule中的的Validate方法来验证我们绑定的属性.所以我们的用法是继承ValidationRule,重写他的Validate方法.示例 public class RequiredRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { if

使用Data Annotations进行手动数据验证

Data Annotations是在Asp.Net中用于表单验证的 它通过Attribute直接标记字段的有效性,简单且直观.在非Asp.Net程序中(如控制台程序),我们也可以使用Data Annotations进行手动数据验证的,一个简单的例子如下(需要添加System.ComponentModel.DataAnnotations.dll的引用): using System; using System.Collections.Generic; using System.Linq; using

【Win10】使用 ValidationAttribute 实现数据验证

WPF 中数据验证的方式多种多样,这里就不说了.但是,在 Windows Phone 8.1 Runtime 中,要实现数据验证,只能靠最基础的手动编写条件判断代码来实现.如果用过 ASP.NET MVC 的那套数据验证的话,再来 WP8.1,那简直就是回到原始社会的感觉. 现在,得益于大一统,mobile 端的 App 也能用上 ValidationAttribute 了!(主要是指 System.ComponentModel.DataAnnotations 这个命名空间下的 Attribut

POI 数据验证

从3.8开始,POI使用.xls和.xlsx格式处理数据校验略有不同之处.1)针对一个或多个预定义值检查用户输入到单元格的值以下代码将限制用户能输入到单元格A1的值是三个整数值(10.20.30)之一:    Workbook workbook = new XSSFWorkbook();  // 或者new HSSFWorkbook    Sheet sheet = workbook.createSheet("Data Validation");    // 数据验证帮助类    Da

strut2 的数据验证

数据验证 用户的输入验证,必须做,且工作量巨大. 1.验证的方式 客户端验证:javascript 服务端验证:逻辑验证(我们的代码) 注意:如果客户端和服务端二选一的话,服务器端的不能省. 实际开发中:客户端+服务端 2.Struts2的服务端验证 2.1.编程式验证 前提:                                    动作类必须继承ActionSupport                             在代码中编写验证规则. a.针对动作类中的所有动作方

我这么玩Web Api(二):数据验证,全局数据验证与单元测试

目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试   一.模型状态 - ModelState 我理解的ModelState是微软在ASP.NET MVC中提出的一种新机制,它主要实现以下几个功能: 1. 保存客户端传过来的数据,如果验证不通过,把数据返回到客户端,这样可以保存用户输入,不需要重新输入. 2. 验证数据,以及保存数据对应的错误信息. 3. 微软的一种DRY(Don't Repeat

数据验证【web前端,表单】

数据验证 最近做后台比较多,路七八糟的数据验证,弄得不厌其烦.SO,弄了个表单验证的玩意出来,达到快速,简介,不烦人的验证. 下面看看,几种方式的数据验证,有什么不同.先有需要验证的数据: <form> <input type="text" name="name" /> <input type="text" name="password" /> <input type="nu