- A+
所属分类:.NET技术
WPF中使用IDataErrorInfo进行数据对象验证
使用 IDataErrorInfo 进行数据对象验证主要有以下步骤:
1、定义一个集合,用于收集错误信息:
private Dictionary<string, string> dataErrors = new Dictionary<string, string>();
2、需要验证的对象的类需要实现 IDataErrorInfo 接口:
- 具体的数据验证在 this[string columnName] 的 get 访问器中进行。为了防止在处理验证信息时进行大量的条件判断,在这里使用了命名空间 System.ComponentModel.DataAnnotations,将验证条件分离,以 Attribute 的形式关联到每个字段上。
- 错误信息在这里存储在集合 dataErrors 中,所以需要补充两个方法,用于操作错误dataErrors 。
- 实现以上处理的 ViewModel 代码如下:
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Windows; namespace IDataErrorInfoDemo.ViewModel { [MetadataType(typeof(MainViewModel))] public class MainViewModel : ViewModelBase, IDataErrorInfo { public MainViewModel() { SaveCommand = new RelayCommand(() => { if (dataErrors.Count == 0) MessageBox.Show("验证通过!"); else { StringBuilder sb = new StringBuilder(); sb.Append("验证失败:rn"); foreach (var error in dataErrors) { sb.Append(error + "rn"); } MessageBox.Show(sb.ToString()); } }); } /// <summary> /// 页面提交命令 /// </summary> public RelayCommand SaveCommand { get; set; } private string userName; /// <summary> /// 用户名 /// </summary> [Required] public string UserName { get { return userName; } set { userName = value; RaisePropertyChanged(); } } private String userEmail; /// <summary> /// 用户邮件 /// </summary> [Required] [StringLength(100, MinimumLength = 2)] [RegularExpression("^\s*([A-Za-z0-9_-]+(\.\w+)*@(\w+\.)+\w{2,5})\s*$", ErrorMessage = "邮箱地址填写错误。")] public String UserEmail { get { return userEmail; } set { userEmail = value; } } /// <summary> /// 错误集合 /// </summary> private Dictionary<string, string> dataErrors = new Dictionary<string, string>(); //IDataErrorInfo的固定实现 public string Error { get; } public string this[string columnName] { get { ValidationContext vc = new ValidationContext(this, null, null); vc.MemberName = columnName; var res = new List<ValidationResult>(); var result = Validator.TryValidateProperty(this.GetType().GetProperty(columnName).GetValue(this, null), vc, res); if (res.Count > 0) { string error = string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray()); AddDic(dataErrors, vc.MemberName, error); return error; } RemoveDic(dataErrors, vc.MemberName); return null; } } /// <summary> /// 移除错误信息 /// </summary> /// <param name="dics"></param> /// <param name="dicKey"></param> private void RemoveDic(Dictionary<string, string> dics, string dicKey) { dics.Remove(dicKey); } /// <summary> /// 添加错误信息 /// </summary> /// <param name="dics"></param> /// <param name="dicKey"></param> private void AddDic(Dictionary<string, string> dics, string dicKey,string dicValue) { if (!dics.ContainsKey(dicKey)) dics.Add(dicKey, dicValue); } } }
3、在 View 中对需要验证的元素的 Binding 开启属性 :ValidatesOnDataErrors=True
<TextBox Text="{Binding UserEmail, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="200" Height="30" />
完整的 View 代码如下:
<Window x:Class="IDataErrorInfoDemo.MainWindow" 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:local="clr-namespace:IDataErrorInfoDemo" Title="MainWindow" Width="800" Height="450" mc:Ignorable="d"> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal"> <Label Content="用户名:" Margin="0,0,10,0" FontSize="20" /> <TextBox Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="200" Height="30" /> </StackPanel> <StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal"> <Label Content="邮箱:" Margin="0,0,10,0" FontSize="20" /> <TextBox Text="{Binding UserEmail, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="200" Height="30" /> </StackPanel> <Button Grid.Row="2" Content="提交" Command="{Binding SaveCommand}" Width="200" Height="30" Margin="0,20,0,0" /> </Grid> </Window>