摘要:在Silverlight 4中,Silverlight Validation有相对的改进,本篇将介绍Silverlight 4中新加入的验证机制功能,IDataErrorInfo客户端同步验证机制

  Silverlight 4 Validation验证实例系列

  前文介绍过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命名空间。该接口主要被应用在需要对其进行验证的数据成员类。

         #region IDataErrorInfo Members
         public string Error
         {
             get { throw new NotImplementedException(); }
         }
 
         public string this[string columnName]
         {
             get { throw new NotImplementedException(); }
         }
        #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中添加简单的逻辑代码。

)
                    _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");
                }
            }
        }

);
                        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>

  其最终运行结果如下:

  今天内容讲到这里了。

  源代码下载

最新文章

  1. [转]OAuth 2.0 - Authorization Code授权方式详解
  2. HDU1760 A New Tetris Game NP态
  3. 跟我一起学WCF(4)——第一个WCF程序
  4. MySQL 强制操作以及order by 使用
  5. 转: JSP中include指令和include动作的区别
  6. @synthesize 有什么好处?
  7. 饶有兴致的用javascript做了个贪食蛇游戏
  8. iOS 2D绘图详解(Quartz 2D)之阴影和渐变(Shadow,Gradient)
  9. Eclipse - FindBugs Plugin 的安装和使用
  10. php的分表分库类
  11. c语言编译预处理和条件编译执行过程的理解
  12. XmlNode中Value和InnerText的区别
  13. Spring4.0学习笔记(2) —— 自动装配
  14. Linux能力(capability)机制的继承
  15. C#和.NET Framework
  16. 编写简单的hashCode方法
  17. linux服务器没网情况下手动安装软件几个方法
  18. GNU/Linux超级本ZaReason Ultralap 440体验
  19. collectionviewcell 添加删除按钮 响应区域的问题
  20. adobe acrobat pro 9破解方法

热门文章

  1. 【博弈论】【SG函数】bzoj1777 [Usaco2010 Hol]rocks 石头木头
  2. 1.2(Spring MVC学习笔记) Spring MVC核心类及注解
  3. Mapper动态代理开发
  4. Jquery中的ajax应用(第九章PPT)
  5. Delphi 获取sqlite中所有的表名
  6. md5代码实现
  7. 常用vim命令合集
  8. HDU 4289 Control (最小割 拆点)
  9. EffectiveJava(23)为什么不能在新生代码中使用原生态类型
  10. PJOI PKU Campus 2011 B:A Problem about Tree LCA 求随意点x为根的y的父节点