Silverlight商业应用程序开发学习笔记(13) 数据输入验证---
2013-07-01 15:10
696 查看
对无效数据的输入进行验证和必要的提示是商业应用程序必备的功能之一。Silverlight使用DataAnnotation特性标记来进行数据的验证,对用户输入数据的合法性进行判断,阻止非法数据提交到服务器,并给出修改提示。
1、验证错误信息的显示
1)数据输入控件:
特征:Label控件变红,输入框变红,在输入框右侧显示红底白色的提示语;
2)ValidationSummary控件
只需要将该控件放在视图中即可:
<sdk:ValidationSummary/>
另外还需要将各个输入控件的NotifyOnValidationError属性设置为True;
显示特征:在顶端显示错误个数;在下边列出错误字段及错误信息;直到所有错误排除后才消失有关提示信息;
3)DataForm控件
显示特征:组合式验证信息显示;
如果AutoCommit属性设置为False,在允许用户提交更新之前,DataForm控件会确保被绑定的实体或对象是有效的;如果AutoCommit属性设置为True,则DataForm控件会阻止用户从当前记录中移出,直到验证错误全部纠正为止。
4)DataGrid控件:
特征:组合式验证错误信息显示;
如果错误未修改将无法添加新行;如果绑定的对象实现了IEditableObject接口,也可以按Esc键退出编辑状态,从而消除错误信息;
2、数据验证的类型
属性级验证
对象级验证:比如结束日期应大于开始日期,这两个属性在同一个对象/实体中;
领域级验证:比如提交订单前应确保库存满足订单的需要,否则无法提交订单;
1)定义验证规则:
对于属性级验证,不管是在实体类还是在ViewModels类中,都可以使用System.ComponentModel.DataAnnotations名称空间下的特性标记进行验证规则定义:
而定义对象级的验证规则,应继承ValidationAttribute类,然后在相应的类上使用该特类生成的特性标识。
2)从对象报告验证错语信息
在Silverlgiht中有几种方式用于从实体/对象报告数据验证信息:
抛出异常
实现IDataErrorInfo接口及相应的行为
实现INotifyDataErrorInfo接口及相应的行为(RIA服务暴露的实体类继承自Entity类,已经实现了INotifyDataErrorInfo接口。)
a)捕捉异常
如果将ValidatesOnExceptions设置为true,则告知绑定引擎捕捉当从
TwoWay绑定中的目标更新源对象时发生的异常。这些异常以两种方式发生:
a).从源对象的setter函数引发。
b).由类型转换器引发。
为了收到已发生这些异常的通知,必须将
NotifyOnValidationError属性设置为true。
如果将此属性设置为false,则该应用程序将在发生验证异常时失败而不给出任何提示。
b)IDataErrorInfo接口
此接口使数据实体类能够实现自定义验证规则并公开用户界面的验证结果。通常实现此接口来提供相对简单的客户端验证逻辑。
IDataErrorInfo.Item属性为整个对象返回一条验证错误消息。
Error属性为整个对象返回一条错误消息。这些单一消息中的每条消息都可表示多个错误。
使用方法
将控件绑定到实现IDataErrorInfo的实体的属性上,并将
Binding.ValidatesOnDataErrors属性设置为true。然后,每当绑定实体的属性更改值时,绑定引擎都会通过将属性名传递到
IDataErrorInfo.Item验证新值。绑定引擎使用这些验证结果,为该绑定更新
Validation.Errors集合。首先,绑定引擎为来自于异常或IDataErrorInfo验证的绑定属性,移除任何现有的错误。然后,如果新值是无效,绑定引擎会为此属性添加一个新错误。
可以同时使用
ValidatesOnExceptions和
ValidatesOnDataErrors;但是,发生的任何异常都会阻止IDataErrorInfo验证。
实现示例:
见http://msdn.microsoft.com/zh-cn/library/system.componentmodel.idataerrorinfo(v=vs.95).aspx;
综合来讲,当实现该接口的对象绑定到控件上以后,控件就会根据验证的结果实时显示出错误的信息,但是其灵活性较差,所以该接口一般不予应用。
c)INotifyDataErrorInfo接口
此接口使数据实体类能够实现自定义验证规则并公开用户界面的验证结果。通常实现此接口来提供服务器端验证逻辑等异步验证逻辑。此接口还支持自定义错误对象、每个属性的多个错误、跨属性错误和实体级错误。
跨属性错误是影响多个属性的错误。您可以将这些错误与一个或所有受影响的属性关联,或者您也可以将它们视为实体级错误。实体级别错误为影响多个属性或影响整个实体的错误,但不影响特定属性。
IDataErrorInfo成员
INotifyDataErrorInfo.HasErrors属性为实体显示当前是否存在任何验证错误。
GetErrors方法返回含有固定属性或整个实体的验证错误的
IEnumerable。您可以实现此方法来为每个受影响的属性在实体级报告跨属性错误,它取决于您的报表需求。
异步验证规则完成处理时,属性或实体的错误
IEnumerable可能改变或被替换。当
ErrorsChanged更改时,一定会发生
IEnumerable事件。事件处理程序可以检索新的HasErrors和
GetErrors值,以便为受影响的属性或实体更新用户界面验证反馈。
GetErrors方法返回的验证错误可以是任何类型。但是,如果您要实现自定义错误类型,一定要重写
ToString方法来返回一条错误消息。Silverlight在其默认错误报告中使用此字符串。
当您在用户界面提供自定义错误报告时,自定义错误对象十分有用。例如,您可以创建报告
ToolTip的模板,以便绑定ErrorLevel属性,并以黄色显示警告信息和以红色显示严重错误。
数据绑定支持。
Silverlight绑定引擎为INotifyDataErrorInfo提供内置支持。若要实现这种支持,只需将控件绑定到实现INotifyDataErrorInfo实体的属性上,或绑定空间到实体本身上。默认情况下,Binding.ValidatesOnNotifyDataErrors
属性必须为true。
绑定引擎调用
GetErrors为绑定属性或实体检索一切初始化错误。如果
Binding.Mode属性值不是
OneTime,则绑定引擎会将
ErrorsChanged事件交给监视器以进行更新。每当绑定属性或实体错误改变,绑定引擎都将调用
GetErrors来检索已更新的错误。尽管您可以在自定义错误报告中使用它,请注意绑定引擎永远不会使用
HasErrors属性。
绑定引擎使用这些验证结果,为该绑定更新
Validation.Errors集合。首先,绑定引擎为来自于异常或INotifyDataErrorInfo验证的绑定属性,移除任何现有的错误。然后,如果新值是无效,绑定引擎会为由
GetErrors方法返回的每个错误添加一个新错误。
INotifyDataErrorInfo错误不会干扰源自
IDataErrorInfo的其他错误。但是,当基于异常的错误处于活动状态时,绑定引擎将不会公开INotifyDataErrorInfo错误。
错误报告
Validation.Errors集合在用户界面中为错误报告提供绑定源。多个控件从其内置错误的模板绑定到此集合中。
若要提供自定义错误报告,您可以替换或修改已有的错误模板。或者,您可以处理
ErrorsChanged事件并直接访问INotifyDataErrorInfo成员。
您也可以将
Binding.NotifyOnValidationError属性设置为true并处理
FrameworkElement.BindingValidationError事件。每次为特定的绑定添加或删除
Validation.Errors时都会发生此事件。有些控件,例如
ValidationSummary,需要这种机制,而不是使用
Validation.Errors集合。
示例:见http://msdn.microsoft.com/zh-cn/library/system.componentmodel.inotifydataerrorinfo(v=vs.95).aspx
相关示例代码随附下载。
3)在视图的后置代码中处理验证错误
按如下步骤进行:
a)设置binding的NotifyOnValidationError和ValidatesOnDataErrors属性为True:
b)在后置代码中处理BindingValidationError事件。
4)使用特性标记验证非RIA元数据类
通过RIA服务暴露的实体可以使用特性标记来进行验证,很方便,但是常规的元数据类如果使用这种标记则不会正常实现验证功能,需要做一些设置.Silverlight的DataAnnotation验证机制,在添加验证属性后,不需要在Setter中进行验证判断,仅需要在Setter中激活该验证属性即可,而要实现激活验证,则需要使用ValidationContext和Validator类。为了更好的理解SilverlightDataAnnotation验证机制,我们来对这两个类进行简单的讲解.
首先说说Validator类,该类是一个静态类,主要用来当数据成员被指定验证元数据属性时,验证对象,属性和方法。简单的理解就是包含了各种具体验证方法的类。例如Require验证属性,Validator类将会根据该验证属性执行对应的验证方法,对目标值进行判断。在该类中,包含ValidateProperty方法(验证错误返回异常)和TryValidateProperty方法(验证错误返回False),可以分别对当前属性进行验证操作。
而ValiationContext类,该类是对当前执行的数据验证提供上下文描述的。简单的理解,也就是为验证提供数据传输,属性标识等任务。
属性验证:
在上文代码中,我们定义一个ValidationContext实例,该实例中包含了需要验证对象的引用,并且,我们定义了验证对象的MemberName,通过调用Validator.ValidateProperty静态方法,检查目标数据是否符合当前验证属性,如果返回False,则抛出一个ValidationException。
上面代码也可简写为:
Validator.ValidateProperty(value,newValidationContext(this,null,null){MemberName="email"});
再比如:
可以看到,除了实现上稍有麻烦,使用方法都是类似的。
对象验证
使用Validator类进行对象验证通常都在IEditableObject接口的EndEdit方法中进行,在该方法中可以调用下列返回值为Boolean的方法,如果返回True则正常更新,如果返回值为False,则处理验证结果:
1、验证错误信息的显示
1)数据输入控件:
特征:Label控件变红,输入框变红,在输入框右侧显示红底白色的提示语;
2)ValidationSummary控件
只需要将该控件放在视图中即可:
<sdk:ValidationSummary/>
另外还需要将各个输入控件的NotifyOnValidationError属性设置为True;
显示特征:在顶端显示错误个数;在下边列出错误字段及错误信息;直到所有错误排除后才消失有关提示信息;
3)DataForm控件
显示特征:组合式验证信息显示;
如果AutoCommit属性设置为False,在允许用户提交更新之前,DataForm控件会确保被绑定的实体或对象是有效的;如果AutoCommit属性设置为True,则DataForm控件会阻止用户从当前记录中移出,直到验证错误全部纠正为止。
4)DataGrid控件:
特征:组合式验证错误信息显示;
如果错误未修改将无法添加新行;如果绑定的对象实现了IEditableObject接口,也可以按Esc键退出编辑状态,从而消除错误信息;
2、数据验证的类型
属性级验证
对象级验证:比如结束日期应大于开始日期,这两个属性在同一个对象/实体中;
领域级验证:比如提交订单前应确保库存满足订单的需要,否则无法提交订单;
1)定义验证规则:
对于属性级验证,不管是在实体类还是在ViewModels类中,都可以使用System.ComponentModel.DataAnnotations名称空间下的特性标记进行验证规则定义:
[Required] [StringLength(50)] [RegularExpression(@"(?<user>[^@]+)@(?<host>.+)")] publicstringEmailAddress; [Range(0,150)] publicintAge;
而定义对象级的验证规则,应继承ValidationAttribute类,然后在相应的类上使用该特类生成的特性标识。
publicclassSellDatesValidationAttribute:ValidationAttribute { protectedoverrideValidationResultIsValid(objectvalue, ValidationContextvalidationContext) { Productproduct=valueasProduct; returnproduct.SellEndDate>product.SellStartDate? ValidationResult.Success:newValidationResult( "Thesellenddatemustbegreaterthanthesellstartdate"); } } 使用方法:
[SellDatesValidation] publicclassProduct
2)从对象报告验证错语信息
在Silverlgiht中有几种方式用于从实体/对象报告数据验证信息:
抛出异常
实现IDataErrorInfo接口及相应的行为
实现INotifyDataErrorInfo接口及相应的行为(RIA服务暴露的实体类继承自Entity类,已经实现了INotifyDataErrorInfo接口。)
a)捕捉异常
publicstringName
{
get{return_name;}
set
{
_name=value;
//Checkvalidationrule
if(string.IsNullOrEmpty(value))
thrownewValidationException("Youmustenteranamefortheproduct");
}
}
<TextBoxText="{BindingName,Mode=TwoWay,ValidatesOnExceptions=True}"/>
如果将ValidatesOnExceptions设置为true,则告知绑定引擎捕捉当从
TwoWay绑定中的目标更新源对象时发生的异常。这些异常以两种方式发生:
a).从源对象的setter函数引发。
b).由类型转换器引发。
为了收到已发生这些异常的通知,必须将
NotifyOnValidationError属性设置为true。
如果将此属性设置为false,则该应用程序将在发生验证异常时失败而不给出任何提示。
b)IDataErrorInfo接口
此接口使数据实体类能够实现自定义验证规则并公开用户界面的验证结果。通常实现此接口来提供相对简单的客户端验证逻辑。
Error属性为整个对象返回一条错误消息。这些单一消息中的每条消息都可表示多个错误。
使用方法
将控件绑定到实现IDataErrorInfo的实体的属性上,并将
Binding.ValidatesOnDataErrors属性设置为true。然后,每当绑定实体的属性更改值时,绑定引擎都会通过将属性名传递到
IDataErrorInfo.Item验证新值。绑定引擎使用这些验证结果,为该绑定更新
Validation.Errors集合。首先,绑定引擎为来自于异常或IDataErrorInfo验证的绑定属性,移除任何现有的错误。然后,如果新值是无效,绑定引擎会为此属性添加一个新错误。
可以同时使用
ValidatesOnExceptions和
ValidatesOnDataErrors;但是,发生的任何异常都会阻止IDataErrorInfo验证。
实现示例:
见
综合来讲,当实现该接口的对象绑定到控件上以后,控件就会根据验证的结果实时显示出错误的信息,但是其灵活性较差,所以该接口一般不予应用。
c)INotifyDataErrorInfo接口
此接口使数据实体类能够实现自定义验证规则并公开用户界面的验证结果。通常实现此接口来提供服务器端验证逻辑等异步验证逻辑。此接口还支持自定义错误对象、每个属性的多个错误、跨属性错误和实体级错误。
跨属性错误是影响多个属性的错误。您可以将这些错误与一个或所有受影响的属性关联,或者您也可以将它们视为实体级错误。实体级别错误为影响多个属性或影响整个实体的错误,但不影响特定属性。
IDataErrorInfo成员
GetErrors方法返回含有固定属性或整个实体的验证错误的
IEnumerable。您可以实现此方法来为每个受影响的属性在实体级报告跨属性错误,它取决于您的报表需求。
异步验证规则完成处理时,属性或实体的错误
IEnumerable可能改变或被替换。当
ErrorsChanged更改时,一定会发生
IEnumerable事件。事件处理程序可以检索新的
GetErrors值,以便为受影响的属性或实体更新用户界面验证反馈。
ToString方法来返回一条错误消息。Silverlight在其默认错误报告中使用此字符串。
当您在用户界面提供自定义错误报告时,自定义错误对象十分有用。例如,您可以创建报告
ToolTip的模板,以便绑定ErrorLevel属性,并以黄色显示警告信息和以红色显示严重错误。
数据绑定支持。
Silverlight绑定引擎为INotifyDataErrorInfo提供内置支持。若要实现这种支持,只需将控件绑定到实现INotifyDataErrorInfo实体的属性上,或绑定空间到实体本身上。默认情况下,
属性必须为true。
绑定引擎调用
GetErrors为绑定属性或实体检索一切初始化错误。如果
Binding.Mode属性值不是
OneTime,则绑定引擎会将
ErrorsChanged事件交给监视器以进行更新。每当绑定属性或实体错误改变,绑定引擎都将调用
GetErrors来检索已更新的错误。尽管您可以在自定义错误报告中使用它,请注意绑定引擎永远不会使用
HasErrors属性。
绑定引擎使用这些验证结果,为该绑定更新
Validation.Errors集合。首先,绑定引擎为来自于异常或INotifyDataErrorInfo验证的绑定属性,移除任何现有的错误。然后,如果新值是无效,绑定引擎会为由
GetErrors方法返回的每个错误添加一个新错误。
INotifyDataErrorInfo错误不会干扰源自
IDataErrorInfo的其他错误。但是,当基于异常的错误处于活动状态时,绑定引擎将不会公开INotifyDataErrorInfo错误。
错误报告
若要提供自定义错误报告,您可以替换或修改已有的错误模板。或者,您可以处理
ErrorsChanged事件并直接访问INotifyDataErrorInfo成员。
您也可以将
Binding.NotifyOnValidationError属性设置为true并处理
FrameworkElement.BindingValidationError事件。每次为特定的绑定添加或删除
Validation.Errors时都会发生此事件。有些控件,例如
ValidationSummary,需要这种机制,而不是使用
Validation.Errors集合。
示例:见
相关示例代码随附下载。
3)在视图的后置代码中处理验证错误
按如下步骤进行:
a)设置binding的NotifyOnValidationError和ValidatesOnDataErrors属性为True:
<TextBoxText="{BindingName,Mode=TwoWay,NotifyOnValidationError=True,
ValidatesOnDataErrors=True}"
BindingValidationError="NameTextBox_BindingValidationError"/>
b)在后置代码中处理BindingValidationError事件。
privatevoidNameTextBox_BindingValidationError(objectsender,
ValidationErrorEventArgse)
{
if(e.Action==ValidationErrorEventAction.Added)
{
//Dosomethingwiththeerror
stringerrorMessage=e.Error.ErrorContent.ToString();
}
}
4)使用特性标记验证非RIA元数据类
通过RIA服务暴露的实体可以使用特性标记来进行验证,很方便,但是常规的元数据类如果使用这种标记则不会正常实现验证功能,需要做一些设置.Silverlight的DataAnnotation验证机制,在添加验证属性后,不需要在Setter中进行验证判断,仅需要在Setter中激活该验证属性即可,而要实现激活验证,则需要使用ValidationContext和Validator类。为了更好的理解SilverlightDataAnnotation验证机制,我们来对这两个类进行简单的讲解.
首先说说
而
属性验证:
privatestring_email;
[Required(ErrorMessage="必填选项")]
publicstringemail
{
get{return_email;}
set
{
vartempValidator=newValidationContext(this,null,null);
tempValidator.MebmerName="email";
Validator.ValidateProperty(value,tempValidator);
_email=value;
}
在上文代码中,我们定义一个ValidationContext实例,该实例中包含了需要验证对象的引用,并且,我们定义了验证对象的MemberName,通过调用Validator.ValidateProperty静态方法,检查目标数据是否符合当前验证属性,如果返回False,则抛出一个ValidationException。
上面代码也可简写为:
Validator.ValidateProperty(value,newValidationContext(this,null,null){MemberName="email"});
再比如:
privatestring_password;
[StringLength(6,ErrorMessage="密码不能超过6个字符")]
publicstringpassword
{
get{return_password;}
set
{
Validator.ValidateProperty(value,newValidationContext(this,null,null){MemberName="password"});
_password=value;
}
}
可以看到,除了实现上稍有麻烦,使用方法都是类似的。
对象验证
使用Validator类进行对象验证通常都在IEditableObject接口的EndEdit方法中进行,在该方法中可以调用下列返回值为Boolean的方法,如果返回True则正常更新,如果返回值为False,则处理验证结果:
publicboolValidate()
{
varvalidationContext=newValidationContext(this,null,null);
varvalidationResults=newList<ValidationResult>();
boolisValid=Validator.TryValidateObject(this,validationContext,
validationResults,true);
_validationErrors.Clear();
foreach(ValidationResultresultinvalidationResults)
{
foreach(stringpropertyNameinresult.MemberNames)
{
List<string>errors=null;
if(_validationErrors.ContainsKey(propertyName))
{
errors=_validationErrors[propertyName];
}
else
{
errors=newList<string>();
_validationErrors[propertyName]=errors;
}
errors.Add(result.ErrorMessage);
if(ErrorsChanged!=null)
ErrorsChanged(this,
newDataErrorsChangedEventArgs(propertyName));
}
}
returnisValid;
}
示例文件下载地址:/Files/qouoww/ValidationDemo.zip
相关文章推荐
- 数据输入验证---Silverlight商业应用程序开发学习笔记(13)
- SilverLight商业应用程序开发---学习笔记(11)常用数据输入控件介绍
- SilverLight商业应用程序开发---学习笔记(6)从服务器中获取数据之二
- SilverLight商业应用程序开发---学习笔记(5)从服务器中获取数据之一
- SilverLight商业应用程序开发---学习笔记(7)
- SilverLight商业应用程序开发---学习笔记(7) DataGrid控件的使用
- SilverLight商业应用程序开发---学习笔记(8)
- SilverLight商业应用程序开发---学习笔记(8) 适用于SilverLight商业应用程序的几个重要的类
- SilverLight商业应用程序开发---学习笔记(10)
- SilverLight商业应用程序开发---学习笔记(4)
- SilverLight商业应用程序开发---学习笔记(3)
- SilverLight商业应用程序开发---学习笔记(11)
- SilverLight商业应用程序开发---学习笔记(9)从摘要信息跳转到详细信息 导航到细节视图 在弹出窗体打开细节视图 使用DataGrid控件的行细节显示特性显示细节内容 主/从视图的实现
- SilverLight商业应用程序开发---学习笔记(10)使用数据源窗口创建DataGrid
- SilverLight商业应用程序开发---学习笔记(2)
- Silverlight商业应用程序开发学习笔记(12) MVVM设计模式相关--
- Silverlight商业应用程序开发--学习笔记(1)
- SilverLight商业应用程序开发---学习笔记(2) WCF RIA服务
- MVVM设计模式相关--Silverlight商业应用程序开发学习笔记(12)
- Silverlight商业应用程序开发--学习笔记(1) 导航框架 navigationFramework