Silverlight实例教程 - Validation客户端同步数据验证

    技术2025-02-27  37

    标签: silverlight 4 Validation 数据验证 实例专题 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://kevinfan.blog.51cto.com/1037293/391488

     

     

    前文介绍过Silverlight Validation中两个数据验证机制,ValidatesOnExceptions异常捕获验 机制DataAnnotation验证机制 , 这两种验证机制,是在Silverlight 3 Validation Framework推出的,其运行方式类似,都是当异常抛出后,应用对异常信息进行捕获,并显示在客户端。在Silverlight 4中,Silverlight Validation有相对的改进,本篇将介绍Silverlight 4中新加入的验证机制功能,IDataErrorInfo客户端同步验证机制。

     

    Silverlight 4 IDataErrorInfo接口概述

    相信熟悉WPF的开发人员都知道,WPF也具有IdataErrorInfo接口,其接口可以无需抛出任何异常,即可对数据进行验证。而 Silverlight的IDataErrorInfo接口就是从WPF中转化来的。与前面两种验证机制相比,Silverlight 4 IDataErrorInfo提供的同步验证方式,不再需要基于异常抛出的基础上来激活验证,简单的理解,就是当值验证失败的时候,不会抛出任何异常信 息。这种验证机制,相对前两种验证机制来说更加灵活。

     

    Silverlight 4 IDataErrorInfo接口类成员

    IDataErrorInfo接口 ,位于System.ComponentModel命名空间。该接口主要被应用在需要对其进行验证的数据成员类。

     

    代码  1            #region  IDataErrorInfo Members  2    3            public   string  Error  4           {  5                get  {  throw   new  NotImplementedException(); }  6           }  7    8            public   string   this [ string  columnName]  9           { 10                get  {  throw   new  NotImplementedException(); } 11           } 12   13            #endregion

     

     

    IDataErrorInfo接口具有两个属性 :

     

    1. Error: 该属性为验证设置属性错误提示信息;

    2. Item: 该属性为错误信息集合,其中索引值为属性名,将其对应的错误信息,设置到指定的被验证控件中;

     

    从MSDN对IdataErrorInfo接口的解释中可以看到,IDataErrorInfo接口,没有任何事件方法被预先定义。也就是 说,IDataErrorInfo接口本身不具备自动激活验证功能。简单的可以理解成为,当验证错误产生时,该错误信息不会自动捕获,然后显示到用户客户 端上。解决该问题,需要引入另外一个接口INotifyPropertyChanged 。对Silverlight早期版本熟悉的开发人员,应该对INotifyPropertyChanged 接口并不陌生,该接口主要功能是当数据成员改变时发出通知到客户端,是Silverlight中最常用的一个接口,这里对该接口不再赘述。

     

    public   class  Customer  : INotifyPropertyChanged

     

     

         public   event  PropertyChangedEventHandler PropertyChanged;      private   void  NotifyPropertyChanged(String info)     {          if  (PropertyChanged  !=   null )         {             PropertyChanged( this new  PropertyChangedEventArgs(info));         }     }

     

     

         public   string  CustomerName     {          get         {              return   this .customerNameValue;         }          set         {              if  (value  !=   this .customerNameValue)             {                  this .customerNameValue  =  value;                 NotifyPropertyChanged( " CustomerName " );             }         }     }

     

     

    在使用了INotifyPropertyChanged 接口后,每当数据成员验证错误产生时,都会执行IDataErrorInfo接口,检测Error和Item属性。但是仅仅使用INotifyPropertyChanged 接口,还无法正常将错误信息显示在客户端,同时也需要在客户端添加新的绑定验证属性ValidatesOnDataErrors , 该属性在默认绑定情况下是False,如果使用IDataErrorInfo接口,则需要使用True,这时,客户端才会显示IDataErrorInfo接口被执行后产生的验证错误信息。

     

    < TextBox Text = " {Binding CustomerName,Mode=TwoWay,ValidatesOnDataErrors=true} "   />

     

    讲到这里,我们可以结合前两篇讲解的绑定验证属性,来理解IDataErrorInfo接口。

    使用IDataErrorInfo接口,必须结合INotifyPropertyChanged接口使用,否则UI无法获取到相对应属性的错误关联信息。

    而使用IDataErrorInfo接口绑定验证属性时,在客户端控件内容绑定中使用ValidatesOnDataErrors = True,

    另外,如果需要使用BindingValidationError事件,在客户端控件内容中,需要再绑定NotifyOnValidationError = True,

    如果需要对异常进行捕获相应,同时,也需要绑定ValidatesOnExceptions = True。

     

    IDataErrorInfo接口使用实例演示

     

    本实例仍旧使用上一篇的实例代码,在其基础上添加对IDataErrorInfo接口的调用,

    首先在User数据成员类中,执行IDataErrorInfo和INotifyPropertyChanged接口

     

            #region  IDataErrorInfo Members          private   string  _dataError  =   string .Empty;          public   string  Error         {              get  {  return  _dataError; }         }          private  Dictionary < string string >  _dataErrors  =   new  Dictionary < string string > ();          public   string   this [ string  columnName]         {              get               {                  if  (_dataErrors.ContainsKey(columnName))                      return  _dataErrors[columnName];                  else                      return   null ;             }         }          #endregion          #region  INotifyPropertyChanged Members          public   event  PropertyChangedEventHandler PropertyChanged;          protected   void  NotifyPropertyChanged( string  propertyName)         {              if  (PropertyChanged  !=   null )                 PropertyChanged( this new  PropertyChangedEventArgs(propertyName));         }          #endregion

     

     

    其中IDataErrorInfo中定义的Dictionary是验证错误集合。而INotifyPropertyChanged是最简单的当数据成员改变时返回通知到客户端,其中没有过多的逻辑代码。

     

    我们使用最简单的数据成员生成一个验证错误,IDataErrorInfo捕获显示作为演示,

     

     在User类中,添加一个Address地址数据成员,

     

             private   string  _address;          public   string  address         {              get             {                  return  _address;             }              set             {                 _address  =  value;             }         }

     

     

    然后在set中添加简单的逻辑代码,

     

             private   string  _address;          public   string  address         {              get             {                  return  _address;             }              set             {                  if  ( string .IsNullOrEmpty(value))                     _dataErrors[ " address " =   " 地址必须填写 " ;                  else   if  (value.Trim().Length  <   6 )                     _dataErrors[ " address " =   " 地址至少6个字 " ;                  else                      if  (_dataErrors.ContainsKey( " address " ))                         _dataErrors.Remove( " address " );                 _address  =  value;                 NotifyPropertyChanged( " address " );             }         }

     

     

    修改前台,添加新的输入框,另外绑定输入框内容到address,

     

     

    < StackPanel  Orientation ="Horizontal"  Margin ="5" >                  < TextBlock  Text ="地   址: "  VerticalAlignment ="Center" />                  < TextBox  x:Name ="txtAddress"  Width ="200"  DataContext =" {Binding Source={StaticResource UserDataContext}} "  Text =" {Binding Path=address, Mode=TwoWay, ValidatesOnDataErrors=True} "   /> </ StackPanel >

     

     

    其运行结果为:

     

     

    下面,我们做一个较为复杂一些的数据验证,

    学生成绩对应表

    A   -  90-100分

    B   -  80-89分

    C   -  70-79分

    D   -  60-69分

    F   -  0-59分

     

    在这个实例中,我们对多个数据成员进行客户端数据验证。

    添加两个新数据成员,gradelevel和graderange,其中使用独立的验证函数ValidateGradeLevelandRange进行数据验证,

     

             private   string  _gradelevel;          public   string  gradelevel         {              get  {  return  _gradelevel; }              set             {                  if  (ValidateGradeLevelandRange(value,graderange))                 {                     _gradelevel  =  value;                     NotifyPropertyChanged( " gradelevel " );                 }             }         }          private   decimal  _graderange;          public   decimal  graderange         {              get  {  return  _graderange; }              set             {                  if  (ValidateGradeLevelandRange(gradelevel, value))                 {                     _graderange  =  value;                     NotifyPropertyChanged( " graderange " );                 }             }         }

     

     

     

    #region  Customize Validation          private   bool  ValidateGradeLevelandRange( string  level,  decimal  range)         {              bool  isValid  =   false ;              if  (level  ==   null )             {                 _dataErrors[ " gradelevel " =   " 成绩等级必须是A,B,C,D,F " ;                  return   false ;             }              else             {                  switch  (level.ToUpper())                 {                      case   " A " :                         isValid  =  (range  >=   90   &&  range  <=   100 );                          break ;                      case   " B " :                         isValid  =  (range  >=   80   &&  range  <=   89 );                          break ;                      case   " C " :                         isValid  =  (range  >=   70   &&  range  <=   79 );                          break ;                      case   " D " :                         isValid  =  (range  >=   60   &&  range  <=   69 );                          break ;                      case   " F " :                         isValid  =  (range  >=   0   &&  range  <=   59 );                          break ;                      default :                         _dataErrors[ " gradelevel " =   " 成绩等级必须是A,B,C,D,F " ;                          return   false ;                 }             }              if  (isValid)             {                  if  (_dataErrors.ContainsKey( " gradelevel " ))                     _dataErrors.Remove( " gradelevel " );                  if  (_dataErrors.ContainsKey( " graderange " ))                     _dataErrors.Remove( " graderange " );             }              else             {                 _dataErrors[ " gradelevel " =   " 成绩等级和成绩范围不符合 " ;                 _dataErrors[ " graderange " =   " 成绩范围和成绩等级不符合 " ;             }              return  isValid;         }          #endregion

     

     

    在前台添加两个成绩输入框,

     

     

                 < StackPanel  Orientation ="Horizontal"  Margin ="5" >                  < TextBlock  Text ="成绩等级: "  VerticalAlignment ="Center" />                  < TextBox  x:Name ="txtGradeLevel"  Width ="200"  DataContext =" {Binding Source={StaticResource UserDataContext}} "  Text =" {Binding Path=gradelevel, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=False, ValidatesOnExceptions=True} "   />              </ StackPanel >              < StackPanel  Orientation ="Horizontal"  Margin ="5" >                  < TextBlock  Text ="成绩范围: "  VerticalAlignment ="Center" />                  < TextBox  x:Name ="txtGradeRange"  Width ="200"  DataContext =" {Binding Source={StaticResource UserDataContext}} "  Text =" {Binding Path=graderange, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=False, ValidatesOnExceptions=True} "   />              </ StackPanel >

     

     

    其最终运行结果如下:

     

     

    今天内容讲到这里了。

     

    源代码下载

    最新回复(0)