原文地址:
介绍
Silverlight 4.0 数据验证:- IDataErrorInfo - 对数据实体类提供自定义验证支持。.NET Framework 也有此接口,可以方便移植
- INotifyDataErrorInfo - 对数据实体类提供自定义验证支持,比 IDataErrorInfo 功能更强大。INotifyDataErrorInfo 支持异步验证,这就意味着其可以通过验证方法调用 Web 服务和用回调方法更新错误集合来添加服务器端验证
示例
1、演示 IDataErrorInfo 的应用IDataErrorInfoModel.cs /* * IDataErrorInfo - 对数据实体类提供自定义验证支持。.NET Framework 也有此接口,可以方便移植 * string Error - 获取对象的验证错误信息 * string this[string columnName] - 获取对象的指定字段的验证错误信息 */ using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace Silverlight40.Binding { public class IDataErrorInfoModel : System.ComponentModel.IDataErrorInfo { // 验证错误的提示信息 private const string ID_ERROR = " id 不能小于 10 "; private const string NAME_ERROR = " name 不能包含空格 "; private const string NAME_WARNING = " name 不能小于 5 个字符 "; // 用于保存验证错误信息。key 保存所验证的字段名称;value 保存对应的字段的验证错误信息列表 private Dictionary<String, List<String>> errors = new Dictionary< string, List< string>>(); private int _id; [Display(Name = " 标识 ")] public int Id { get { return _id; } set { if (value > 1000) throw new Exception( " 太大了 "); if (IsIdValid(value) && _id != value) _id = value; } } private string _name; [Display(Name = " 名称 ")] public string Name { get { return _name; } set { if (IsNameValid(value) && _name != value) _name = value; } } public bool IsIdValid( int value) { bool isValid = true; if (value < 10) { AddError( " Id ", ID_ERROR); isValid = false; } else { RemoveError( " Id ", ID_ERROR); } return isValid; } public bool IsNameValid( string value) { bool isValid = true; if (value.Contains( " ")) { AddError( " Name ", NAME_ERROR); isValid = false; } else { RemoveError( " Name ", NAME_ERROR); } if (value.Length < 5) { AddError( " Name ", NAME_WARNING); isValid = false; } else { RemoveError( " Name ", NAME_WARNING); } return isValid; } public void AddError( string propertyName, string error) { if (!errors.ContainsKey(propertyName)) errors[propertyName] = new List< string>(); if (!errors[propertyName].Contains(error)) errors[propertyName].Add(error); } public void RemoveError( string propertyName, string error) { if (errors.ContainsKey(propertyName) && errors[propertyName].Contains(error)) { errors[propertyName].Remove(error); if (errors[propertyName].Count == 0) errors.Remove(propertyName); } } public string Error { get { return errors.Count > 0 ? " 有验证错误 " : " 没有验证错误 "; } } public string this[ string propertyName] { get { if (errors.ContainsKey(propertyName)) return string.Join(Environment.NewLine, errors[propertyName]); else return null; } } } }
IDataErrorInfo.xaml
< navigation:Page x:Class ="Silverlight40.Binding.IDataErrorInfo" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d ="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:navigation ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" xmlns:sdk ="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Title ="IDataErrorInfo Page" > < Grid x:Name ="LayoutRoot" > < StackPanel HorizontalAlignment ="Left" > < sdk:ValidationSummary Margin ="3" > < sdk:ValidationSummary.Header > 错误列表: </ sdk:ValidationSummary.Header > </ sdk:ValidationSummary > <!-- ValidatesOnExceptions - 指定绑定引擎是否报告验证过程中的异常信息 ValidatesOnDataErrors - 指定绑定引擎是否报告绑定数据实体上的 IDataErrorInfo 所实现的验证错误信息(通过 IDataErrorInfo 的 this[string columnName] 获取验证错误信息) NotifyOnValidationError - 当出现验证错误时是否触发 BindingValidationError 事件 --> < StackPanel Orientation ="Horizontal" > < sdk:Label Target =" {Binding ElementName=txtId} " /> < TextBox Name ="txtId" Text =" {Binding Id, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, NotifyOnValidationError=True} " KeyDown ="txtId_KeyDown" /> < sdk:DescriptionViewer Description ="id 不能小于 10" /> </ StackPanel > < StackPanel Orientation ="Horizontal" > < sdk:Label Target =" {Binding ElementName=txtName} " /> < TextBox Name ="txtName" Text =" {Binding Name, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True, NotifyOnValidationError=True} " KeyDown ="txtName_KeyDown" /> < sdk:DescriptionViewer Description ="name 不能包含空格且 name 不能小于 5 个字符" /> </ StackPanel > < Button Name ="btnSubmit" Content ="获取验证信息" Click ="btnSubmit_Click" /> </ StackPanel > </ Grid > </ navigation:Page >
IDataErrorInfo.xaml.cs
/* * 通过绑定实现了 IDataErrorInfo 接口的实体类来实现自定义数据验证功能 */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Navigation; namespace Silverlight40.Binding { public partial class IDataErrorInfo : Page { IDataErrorInfoModel _model; public IDataErrorInfo() { InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { _model = new IDataErrorInfoModel() { Id = 100, Name = " webabcd " }; LayoutRoot.DataContext = _model; // BindingValidationError - 当有数据验证错误时所触发的事件。绑定时需要设置 NotifyOnValidationError=True txtId.BindingValidationError += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); }; txtName.BindingValidationError += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); }; } private void txtId_KeyDown( object sender, KeyEventArgs e) { // 注: // BindingValidationError 事件只有在控件失去焦点才会被触发 // 如果需要在控件没失去焦点的情况下产生验证效果,那么可以通过调用 BindingExpression.UpdateSource() 方法来实现 // FrameworkElement.GetBindingExpression(DependencyProperty dp) - 获取 FrameworkElement 的指定属性上的绑定信息 // BindingExpression.UpdateSource() - 将当前绑定信息立即发送到绑定方式为 TwoWay 的属性上 if (e.Key == System.Windows.Input.Key.Enter) txtId.GetBindingExpression(TextBox.TextProperty).UpdateSource(); } private void txtName_KeyDown( object sender, KeyEventArgs e) { if (e.Key == System.Windows.Input.Key.Enter) txtName.GetBindingExpression(TextBox.TextProperty).UpdateSource(); } private void btnSubmit_Click( object sender, RoutedEventArgs e) { MessageBox.Show( " 验证信息: " + _model.Error); } } }
2、演示 INotifyDataErrorInfo 的应用
INotifyDataErrorInfoModel.cs /* * INotifyDataErrorInfo - 对数据实体类提供自定义验证支持,比 IDataErrorInfo 功能更强大。INotifyDataErrorInfo 支持异步验证,这就意味着其可以通过验证方法调用 Web 服务和用回调方法更新错误集合来添加服务器端验证 * bool HasErrors - 对象是否有验证错误信息 * event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged - 当对象的验证错误信息发生改变时所触发的事件 * IEnumerable GetErrors(string propertyName) - 获取对象的指定字段的验证错误信息 */ using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel; namespace Silverlight40.Binding { public class INotifyDataErrorInfoModel : System.ComponentModel.INotifyDataErrorInfo { // 验证错误的提示信息 private const string ID_ERROR = " id 不能小于 10 "; private const string NAME_ERROR = " name 不能包含空格 "; private const string NAME_WARNING = " name 不能小于 5 个字符 "; // 用于保存验证错误信息。key 保存所验证的字段名称;value 保存对应的字段的验证错误信息列表 private Dictionary<String, List<String>> errors = new Dictionary< string, List< string>>(); private int _id; [Display(Name = " 标识 ")] public int Id { get { return _id; } set { if (value > 1000) throw new Exception( " 太大了 "); if (IsIdValid(value) && _id != value) _id = value; } } private string _name; [Display(Name = " 名称 ")] public string Name { get { return _name; } set { if (IsNameValid(value) && _name != value) _name = value; } } public bool IsIdValid( int value) { bool isValid = true; if (value < 10) { AddError( " Id ", ID_ERROR); isValid = false; } else { RemoveError( " Id ", ID_ERROR); } return isValid; } public bool IsNameValid( string value) { bool isValid = true; if (value.Contains( " ")) { AddError( " Name ", NAME_ERROR); isValid = false; } else { RemoveError( " Name ", NAME_ERROR); } if (value.Length < 5) { AddError( " Name ", NAME_WARNING); isValid = false; } else { RemoveError( " Name ", NAME_WARNING); } return isValid; } public void AddError( string propertyName, string error) { if (!errors.ContainsKey(propertyName)) errors[propertyName] = new List< string>(); if (!errors[propertyName].Contains(error)) { errors[propertyName].Add(error); RaiseErrorsChanged(propertyName); } } public void RemoveError( string propertyName, string error) { if (errors.ContainsKey(propertyName) && errors[propertyName].Contains(error)) { errors[propertyName].Remove(error); if (errors[propertyName].Count == 0) errors.Remove(propertyName); RaiseErrorsChanged(propertyName); } } public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; public void RaiseErrorsChanged( string propertyName) { if (ErrorsChanged != null) ErrorsChanged( this, new DataErrorsChangedEventArgs(propertyName)); } public System.Collections.IEnumerable GetErrors( string propertyName) { if (errors.ContainsKey(propertyName)) return errors[propertyName]; else return null; } public bool HasErrors { get { return errors.Count > 0; } } } }
INotifyDataErrorInfo.xaml
< navigation:Page x:Class ="Silverlight40.Binding.INotifyDataErrorInfo" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d ="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:navigation ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" xmlns:sdk ="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Title ="INotifyDataErrorInfo Page" > < Grid x:Name ="LayoutRoot" > < StackPanel HorizontalAlignment ="Left" > < sdk:ValidationSummary Margin ="3" > < sdk:ValidationSummary.Header > 错误列表: </ sdk:ValidationSummary.Header > </ sdk:ValidationSummary > <!-- ValidatesOnExceptions - 指定绑定引擎是否报告验证过程中的异常信息 NotifyOnValidationError - 当出现验证错误时是否触发 BindingValidationError 事件 --> < StackPanel Orientation ="Horizontal" > < sdk:Label Target =" {Binding ElementName=txtId} " /> < TextBox Name ="txtId" Text =" {Binding Id, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True} " KeyDown ="txtId_KeyDown" /> < sdk:DescriptionViewer Description ="id 不能小于 10" /> </ StackPanel > < StackPanel Orientation ="Horizontal" > < sdk:Label Target =" {Binding ElementName=txtName} " /> < TextBox Name ="txtName" Text =" {Binding Name, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True} " KeyDown ="txtName_KeyDown" /> < sdk:DescriptionViewer Description ="name 不能包含空格且 name 不能小于 5 个字符" /> </ StackPanel > < Button Name ="btnSubmit" Content ="是否有验证错误" Click ="btnSubmit_Click" /> </ StackPanel > </ Grid > </ navigation:Page >
INotifyDataErrorInfo.xaml.cs
/* * 通过绑定实现了 INotifyDataErrorInfo 接口的实体类来实现自定义数据验证功能 */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Navigation; namespace Silverlight40.Binding { public partial class INotifyDataErrorInfo : Page { INotifyDataErrorInfoModel _model; public INotifyDataErrorInfo() { InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { _model = new INotifyDataErrorInfoModel() { Id = 100, Name = " webabcd " }; LayoutRoot.DataContext = _model; // BindingValidationError - 当有数据验证错误时所触发的事件。绑定时需要设置 NotifyOnValidationError=True txtId.BindingValidationError += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); }; txtName.BindingValidationError += (x, y) => { MessageBox.Show(y.Error.ErrorContent.ToString()); }; } private void txtId_KeyDown( object sender, KeyEventArgs e) { // 注: // BindingValidationError 事件只有在控件失去焦点才会被触发 // 如果需要在控件没失去焦点的情况下产生验证效果,那么可以通过调用 BindingExpression.UpdateSource() 方法来实现 // FrameworkElement.GetBindingExpression(DependencyProperty dp) - 获取 FrameworkElement 的指定属性上的绑定信息 // BindingExpression.UpdateSource() - 将当前绑定信息立即发送到绑定方式为 TwoWay 的属性上 if (e.Key == System.Windows.Input.Key.Enter) txtId.GetBindingExpression(TextBox.TextProperty).UpdateSource(); } private void txtName_KeyDown( object sender, KeyEventArgs e) { if (e.Key == System.Windows.Input.Key.Enter) txtName.GetBindingExpression(TextBox.TextProperty).UpdateSource(); } private void btnSubmit_Click( object sender, RoutedEventArgs e) { MessageBox.Show( " 是否有验证错误: " + _model.HasErrors.ToString()); } } }