虽然wpf内部有验证方案,但在实际应用中,会出现一些问题.这里发出来与大家共同讨论.作为使用者,你喜欢哪一种呢?这里不解释数据绑定的知识,因为不够专业,怕会误导,索性不写.但我相信大家会遇到这个问题.本文是通过多个示例比较得出的想法.

1.通过继承ValidationRule抽象类,定义验证规则重写Validate方法

这里是sdk的示例代码

Code
public class AgeRangeRule : ValidationRule
    {
        private int _min;
        private int _max;

        public AgeRangeRule()
        {
        }

        public int Min
        {
            get { return _min; }
            set { _min = value; }
        }

        public int Max
        {
            get { return _max; }
            set { _max = value; }
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            int age = 0;

            try
            {
                if (((string)value).Length > 0)
                    age = Int32.Parse((String)value);
            }
            catch (Exception e)
            {
                return new ValidationResult(false, "Illegal characters or " + e.Message);
            }

            if ((age < Min) || (age > Max))
            {
                return new ValidationResult(false,
                  "Please enter an age in the range: " + Min + " - " + Max + ".");
            }
            else
            {
                return new ValidationResult(true, null);
            }
        }
    }

然后是xaml的使用代码

    <TextBox Name="textBox1" Width="50" FontSize="15"
             Validation.ErrorTemplate="{StaticResource validationTemplate}"
             Style="{StaticResource textBoxInError}"
             Grid.Row="1" Grid.Column="1" Margin="2">
      <TextBox.Text>
        <Binding Path="Age" Source="{StaticResource ods}"
                 UpdateSourceTrigger="PropertyChanged" >
          <Binding.ValidationRules>
            <c:AgeRangeRule Min="21" Max="130"/>
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>

就是通过ValidationRules集合挂验证规则.如果逻辑不复杂的话,勉强可以接受,这里我个人认为可以作为界面的验证.但如果业务逻辑一旦发生变化,则意味着xaml文件一直需要修改,这并不是一种好的做法,并不推荐.(而且内置的验证规则太少了,有的话还勉强用用,都需要自己重写)

2.通过正则表达式附加属性简化写法,大家应该知道,验证部分,正则表达式占了很大部分.

定义一个正则表达式类,然后通过附加属性进行验证.具体的方案,请参考这里
http://www.codeproject.com/WPF/RegexValidationInWPF.asp
然后前端xaml的使用方法

    <TextBox
      Text="{Binding Path=EmailAddress, UpdateSourceTrigger=PropertyChanged}" 
      jas:RegexValidator.RegexText="^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$" 
      jas:RegexValidator.ErrorMessage="Invalid e-mail address." 
      />

代码是简化了,但有个缺点,只能定义一个验证规则,也存在着我上面提到的问题,把正则写在ui上面,并不是一个好的做法,应该对其进行封装(看着这么多符号就心慌,高手可以这么做),也并不推荐的做法.

3.与业务逻辑验证绑定在一起
这种做法与上面的都不同,因为业务逻辑的判断与常规的判断比如(比如是否必填,字符匹配等),而且前端只需要绑定字段就可以了,先看前端的做法

<TextBox Width="100" Grid.Column="1" HorizontalAlignment="Left" Margin="5,5,0,5" x:Name="txtFirstName" Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True}" ToolTip="Enter customers first name." />

请注意,这里并没有写什么验证规则或正则表达式哦,真正的验证在这里,验证的对象必须实现IDataErrorInfo接口,通过索引器,可以判断对象的每个字段.
上面紧紧是FirstName,这里是通过整个对象的业务逻辑判断的,否则你需要在ui上面都定义一个验证规则,非常麻烦(比如有2个字段,你必须对两个字段都定义验证规则(即第一种方法)).这种做法是比较好的,把逻辑与ui分开了,值得推荐.sdk示例代码

 public class Person : IDataErrorInfo
    {
        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }

        public string Error
        {
            get
            {
                return null;
            }
        }

        public string this[string name]
        {
            get
            {
                string result = null;

                if (name == "Age")
                {
                    if (this.age < 0 || this.age > 150)
                    {
                        result = "Age must not be less than 0 or greater than 150.";
                    }
                }
                return result;
            }
        }
    }

但还有些问题,如果我在第3点的基础上,我还要加一个普通的判断,比如必填验证,长度验证,还是逃不了验证规则这一步.
这里我们要做出选择
把规则定义在ui上(变动太大,不适合,无奈之举)
写在业务逻辑里面(这样下来,逻辑未免太复杂)

4.以元数据的形式(在属性上挂标签)

在codeproject上,我找到一个比较完美的解决方案,作者自己重新定义了一套标签,使用也比较简单(代码是vb的,编译后再反编译用c#看:)),这种做法已经接近了要求.大家去看看这篇文章,非常的不错.其在还为前端提供了一个ui显示错误的一个下拉列表.不过通过这个例子,我又想到一个更好的东西.

5.使用EnterPrise Library Validation Application Block(再好不过)
由于wpf的属性使用了大量的依赖属性,我原以为这个好东西在wpf算是废了,通过第3点和第4点,我们终于可以引进这个企业级模块了。如下做法

Code
    public abstract class BaseValidationEntity<T> : IDataErrorInfo, INotifyPropertyChanged
    {
        IDataErrorInfo Members#region IDataErrorInfo Members

        public string Error
        {
            get { return null; }
        }

        private T _entity;

        public bool Valid()
        {
            Validator<T> validator = ValidationFactory.CreateValidator<T>();
            ValidationResults results = validator.Validate(this);
            return results.Count == 0;
        }

        public string this[string name]
        {
            get
            {
                
                string result = null;
                
                Validator<T> validator = ValidationFactory.CreateValidator<T>();
                ValidationResults results = validator.Validate(this);
                if (results.Count > 0)
                {
                    return results.First().Message;
                    //foreach (var item in results)
                    //{
                    //    result += item.Message;
                    //}
                }

                return result;
            }
        }

        #endregion

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }


        INotifyPropertyChanged Members#region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

然后继承之,随便定一个对象来demo

   public class aa:BaseValidationEntity<aa>
    {
        private string firstName;

        [StringLengthValidator(4, 10,MessageTemplate="aaa")]
        [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", MessageTemplate = "Invalid e-mail address")]
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value;
            OnPropertyChanged("FirstName");
            }
        }
    }

我们看到熟悉的标签了,目前我认为这种方案最好,当然我们也可以通过配置xml来实现,这样真正做到了界面与逻辑分离。

上面一层的做到了逻辑上的验证,至于界面如何显示错误,我们可以通过Error属性来定制一个控件,这个暂不讨论了

在学习wpf的朋友,欢迎一起讨论。

参考文章
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx

转载于:https://www.cnblogs.com/junbird-nest/archive/2012/06/18/2553739.html

俊鸟的数据输入校验专题(三) WPF 的五种输入校验概述相关推荐

  1. 串口MSComm控件五种不同校验方式对数据收发的影响

    (2008-09-10 14:50:00)   http://blog.sina.com.cn/s/blog_470eccc60100arq7.html   串口MSComm控件有五种校验方式,分别是 ...

  2. activeform表单中的旧数据怎么显示_三分钟为你细数 Vue el-form 表单校验的坑点

    背景 Vue 的 el-form 提供了表单校验功能,通过 :rules 属性设置校验规则,并通过 el-form-item 的 prop 属性绑定校验规则.通过封装,让前端校验更方便.具体使用过程中 ...

  3. IM扫码登录技术专题(三):通俗易懂,IM扫码登录功能详细原理一篇就够

    本文引用了作者"大古同学"的"二维码扫码登录是什么原理"一文的主要内容,为了更好的理解和阅读,即时通讯网收录时有修订和改动,感谢原作者的分享. 1.引言 自从微 ...

  4. 数据与广告系列三十二:重排ReRank,广告推荐算法链路上的背叛者,生态系统格局的重塑者...

    作者·黄崇远 『数据虫巢』 全文23138字 题图ssyer.com " 在推荐系统又或者计算广告中,重排ReRank明目张胆的把召回.粗排.精排几个链路逻辑辛苦生成的序给打乱,但却敢号称是 ...

  5. 新手入门刷题(专题三)暴力枚举

    新手入门刷题(专题三)暴力枚举--->持续更新 4.14 统计方形(数据加强版) 题目描述 有一个 n×m 方格的棋盘,求其方格包含多少正方形.长方形(不包含正方形). 输入格式 一行,两个正整 ...

  6. 数据体系和专题分析实战。

    来源:产品遇上运营 链接:https://coffee.pmcaff.com/article/1900050815295616/pmcaff?utm_source=forum&newwindo ...

  7. 数据体系和专题分析实战

    来源:产品遇上运营 链接:https://coffee.pmcaff.com/article/1900050815295616/pmcaff?utm_source=forum&newwindo ...

  8. mysql 优化表 3000万_mysql优化:专题三、关于单表查询,可以这么优化

    mysql优化:专题三.关于单表查询,可以这么优化 作者:PHPYuan 时间:2018-10-18 03:41:26 上篇讲解了「mysql优化专题」90%程序员都会忽略的增删改优化(2),相信大家 ...

  9. el-input 输入框类型;只能输入数字的输入框;保留两位小数输入框;只能输入正整数和0的输入框;手机号正则校验;车牌号码正则校验

    以下代码可直接复制使用: 以下代码可直接复制使用! <template><div><a href="https://baike.baidu.com/item/% ...

最新文章

  1. 研究表明:安卓和iOS应用无节操滥用邮箱和定位数据
  2. 2018/12/07 L1-033 出生年 Java
  3. python验证数学原理_一起学opencv-python九(性能的测量和优化与图像处理的数学原理)...
  4. JavaScript高级程序设计之基本概念篇
  5. 中石油训练赛 - Watch Later(状压dp)
  6. 三十岁左右的你正处于什么状态?
  7. 几大经典算法c语言cnds,各种算法的性能分析.docx
  8. Flutter 本地小说阅读器
  9. 用友NC NCCLOUD CNVD高危漏洞修复补丁
  10. android定时器常用方法,Android计时器的三种实现方式
  11. C#注册Email发送验证码详解
  12. 音频怎么转换mp3格式?
  13. 七夕,眼光长远点,聊点孩子的事?
  14. 华为云服务器安装宝塔到服务器
  15. 计算机网络协议有时序,计算机网络协议.doc
  16. 知乎自动化登录(2021.3)
  17. shell脚本练习(随机取名)
  18. 【笔记】Polygon mesh processing 读书笔记(1)
  19. 大学生选课抢课如何提高选中概率
  20. python signal模块作用_Python中的signal模块和Ctrl+C操作

热门文章

  1. “真三”中的人生哲理
  2. 完全二叉树的结点个数
  3. 返回多维数组中某一维的最大值
  4. C++ vector容器删除操作
  5. c++ 该使用类内初始值么?
  6. 为了在 Windows 上安装 GCC
  7. linux5.5 dvd安装教程,linux 5.5 yum的安装方法(ftp)
  8. select、poll、epoll之间的区别
  9. Hadoop组件基本操作
  10. Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'的解决