2021年2月4日星期四

【WPF学习笔记】WPF中使用ValidationRule自定义验证规则

WPF中使用ValidationRule自定义验证规则

本文主要是展示在 WPF 中使用 ValidationRule 自定义验证规则,同时展示两种错误响应方式。一种是通过 Behavior 传递到 ViewModel 中,然后进行错误信息响应;一种是直接在 View 中遍历当前也的所有错误元素,在页面中通过事件统一响应。

1、自定义验证规则类

这里自定义两个验证规则类,分别用于验证 "用户名"输入不可为空、"邮箱"输入值需满足格式要求。

两个类需要继承 ValidationRule 类。ValidationRule 是抽象类,需要具体实现 Validate 方法。代码如下:

NotEmptyValidationRule.cs

using System.Globalization;using System.Windows.Controls;namespace MyValidationRuleDemo.MyValidationRules{ public class NotEmptyValidationRule : ValidationRule {  public override ValidationResult Validate(object value, CultureInfo cultureInfo)  {   return string.IsNullOrWhiteSpace((value ?? "").ToString()) ?    new ValidationResult(false, "不能为空") : new ValidationResult(true, null);  } }}

EmailValidationRule.cs

using System.Globalization;using System.Text.RegularExpressions;using System.Windows.Controls;namespace MyValidationRuleDemo.MyValidationRules{ public class EmailValidationRule : ValidationRule {  public override ValidationResult Validate(object value, CultureInfo cultureInfo)  {   Regex emailRegex = new Regex("^\\s*([A-Za-z0-9_-]+(\\.\\w+)*@(\\w+\\.)+\\w{2,5})\\s*$");   string str = (value ?? "").ToString();   if (!string.IsNullOrWhiteSpace(str))   {    if (!emailRegex.IsMatch(str))    {     return new ValidationResult(false, "邮箱地址错误!");    }   }   return new ValidationResult(true, null);  } }}

2、在前端页面中添加验证

在前端页面中需要进行以下操作:

  1. 添加自定义的 ValidationRule 所有的命名空间;

  2. 在需要验证的控件上的 Binding 上对应的自定义验证规则类;

    <Binding.ValidationRules>	<valRules:EmailValidationRule /></Binding.ValidationRules>

具体代码如下:

<Window x: 

前端页面绑定的验证参数具体如下:

using GalaSoft.MvvmLight;using GalaSoft.MvvmLight.Command;namespace MyValidationRuleDemo.ViewModel{ public class MainViewModel : ViewModelBase {  public MainViewModel()  {  }  private string userName;  /// <summary>  /// 用户名  /// </summary>  public string UserName  {   get { return userName; }   set { userName = value; RaisePropertyChanged(); }  }  private string userEmail;  /// <summary>  /// 用户邮件  /// </summary>  public string UserEmail  {   get { return userEmail; }   set { userEmail = value; RaisePropertyChanged(); }  } }}

此时,自定义的验证规则已经生效。当页面输入不符合规则时,会默认的红框进行标记。这是 WPF 中默认的效果。效果如下图:

ValidationRule01

3、使用 Behavior 自定义响应效果

上面虽然已经在页面上有了基本的错误响应效果,但是效果过于单一。这里我们在这里使用 Behavior 监听 Validation.Error 事件,并将错误信息传递到 ViewModel 中进行统一进行错误提醒。同时,在 MVMM 架构中将错误信息传递到 ViewModel 中进行统一处理,在有需要的时候也有利于业务逻辑处理。

3.1、实现步骤

进行以上操作需要进行以下步骤:

  1. 开启验证错误的通知属性 NotifyOnValidationError="True" 。这样就可以产生 Validation.Error 事件。

    <TextBox Width="200" Height="30"> <TextBox.Text>  <Binding     Path="UserEmail"     NotifyOnValidationError="True"     UpdateSourceTrigger="PropertyChanged">   <Binding.ValidationRules>    <valRules:EmailValidationRule />   </Binding.ValidationRules>  </Binding> </TextBox.Text></TextBox>
  2. 通过自定义的 ValidationExceptionBehavior 继承于 Behavior,用于监听 Validation.Error 的错误事件。

    protected override void OnAttached(){ //添加 Validation.Error 事件监听 this.AssociatedObject.AddHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(OnValidationError));}
  3. View 中添加 Behavior;

    <i:Interaction.Behaviors> <local:ValidationExceptionBehavior /></i:Interaction.Behaviors>
  4. 在 ValidationExceptionBehavior 中通过 AssociatedObject 的DataContext 获取到关联当前View的ViewModel。并将错误提示统一收集到 ViewModel 的 ErrorList 。

    private void OnValidationError(Object sender, ValidationErrorEventArgs e){ MainViewModel mainModel = null; if (AssociatedObject.DataContext is MainViewModel) {  mainModel = this.AssociatedObject.DataContext as MainViewModel; } if (mainModel == null) return; //OriginalSource 触发事件的元素 var element = e.OriginalSource as UIElement; if (element == null) return; //ValidationErrorEventAction.Added 表示新产生的行为 if (e.Action == ValidationErrorEventAction.Added) {  mainModel.ErrorList.Add(e.Error.ErrorContent.ToString()); } else if (e.Action == ValidationErrorEventAction.Removed) //ValidationErrorEventAction.Removed 该行为被移除,即代表验证通过 {  mainModel.ErrorList.Remove(e.Error.ErrorContent.ToString()); }}
  5. 在 View 中按钮绑定的 Command 中统一处理 ErrorList;

    public RelayCommand SaveCommand { get; set; }public MainViewModel(){ SaveCommand = new RelayCommand(() =>         {          StringBuilder sb = new StringBuilder();          foreach (var error in ErrorList)          {           sb.Append(error + "\r\n");          }          MessageBox.Show(sb.ToString());         });}
  6. 开启 ValidationRule 的属性 ValidatesOnTargetUpdated="True",否则在加载页面后,文本框中未输入值则不会进行验证。

    <Binding.ValidationRules> <valRules:EmailValidationRule ValidatesOnTargetUpdated="True" /></Binding.ValidationRules>

3.2、具体代码

完整代码如下:

ValidationExceptionBehavior.cs

using MyValidationRuleDemo.ViewModel;using System;using System.Windows;using System.Windows.Controls;using System.Windows.Interactivity;namespace MyValidationRuleDemo{ public class ValidationExceptionBehavior : Behavior<FrameworkElement> {  protected override void OnAttached()  {   //添加 Validation.Error 事件监听   this.AssociatedObject.AddHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(OnValidationError));  }  private void OnValidationError(Object sender, ValidationErrorEventArgs e)  {   MainViewModel mainModel = null;   if (AssociatedObject.DataContext is MainViewModel)   {    mainModel = this.AssociatedObject.DataContext as MainViewModel;   }   if (mainModel == null) return;   //OriginalSource 触发事件的元素   var element = e.OriginalSource as UIElement;   if (element == null) return;   //ValidationErrorEventAction.Added 表示新产生的行为   if (e.Action == ValidationErrorEventAction.Added)   {    mainModel.ErrorList.Add(e.Error.ErrorContent.ToString());   }   else if (e.Action == ValidationErrorEventAction.Removed) //ValidationErrorEventAction.Removed 该行为被移除,即代表验证通过   {    mainModel.ErrorList.Remove(e.Error.ErrorContent.ToString());   }  }  protected override void OnDetaching()  {   //移除 Validation.Error 事件监听   this.AssociatedObject.RemoveHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(OnValidationError));  } }}

MainView.xaml

<Window x: 

MainViewModel.cs

using GalaSoft.MvvmLight;using GalaSoft.MvvmLight.Command;using System.Collections.ObjectModel;using System.Text;using System.Windows;namespace MyValidationRuleDemo.ViewModel{ public class MainViewModel : ViewModelBase {  public MainViewModel()  {   SaveCommand = new RelayCommand(() =>   {    StringBuilder sb = new StringBuilder();    foreach (var error in ErrorList)    {     sb.Append(error + "\r\n");    }    MessageBox.Show(sb.ToString());   });  }  public RelayCommand SaveCommand { get; set; }  private string userName;  /// <summary>  /// 用户名  /// </summary>  public string UserName  {   get { return userName; }   set { userName = value; RaisePropertyChanged(); }  }  private string userEmail;  /// <summary>  /// 用户邮件  /// </summary>  public string UserEmail  {   get { return userEmail; }   set { userEmail = value; RaisePropertyChanged(); }  }  private ObservableCollection<string> errorList = new ObservableCollection<string>();  /// <summary>  /// 错误提示  /// </summary>  public ObservableCollection<string> ErrorList  {   get { return errorList; }   set { errorList = value; RaisePropertyChanged(); }  } }}

3.3、效果展示

ValidationRule02

4、直接在页面中进行错误响应

错误响应也可以直接在 View 中通过事件直接处理。但是这样处理就比较麻烦,在获取错误列表时,我们可能需要编写代码,从而在 View 中所有控件中查询有错误的控件。

4.1、单个错误响应

Error 事件是使用冒泡策略的路出事件,我们在 Binding 了 ValidationRule 的控件的父容器上关联处理程序,即可为多个控件处理 Error 事件。

在 View.xaml 中添加如下代码:

<Grid Validation.Error="Grid_Error"> <!--这里面是具体的页面内容--></Grid>

关联的事件处理程序如下:

private void Grid_Error(object sender, ValidationErrorEventArgs e){ if (e.Action == ValidationErrorEventAction.Added) {  MessageBox.Show(e.Error.ErrorContent.ToString()); }}

4.2、获取错误列表

循环遍历整个 View 中的元素,并将存在的错误信息收集到一个字符串中,然后点击按钮时将该字符串中的信息展示出来。程序代码如下:

private void Button_Click(object sender, RoutedEventArgs e){ string message; if (HasErrors(out message)) {  MessageBox.Show(message); }}private bool HasErrors(out string message){ StringBuilder sb = new StringBuilder(); GetError(sb, this.grid); message = sb.ToString(); return !string.IsNullOrWhiteSpace(message);}private void GetError(StringBuilder sb, DependencyObject obj){ foreach (object child in LogicalTreeHelper.GetChildren(obj)) {  StackPanel element = child as StackPanel;  if (element == null) continue;  foreach (var ele in element.Children)  {   TextBox textBox = ele as TextBox;   if (textBox == null) continue;   if (Validation.GetHasError(textBox))   {    foreach (ValidationError error in Validation.GetErrors(textBox))    {     sb.Append(error.ErrorContent.ToString() + "\r\n");    }    GetError(sb, element);   }  } }}








原文转载:http://www.shaoqun.com/a/527601.html

跨境电商:https://www.ikjzd.com/

etoro:https://www.ikjzd.com/w/1402

声网agora:https://www.ikjzd.com/w/2176


WPF中使用ValidationRule自定义验证规则本文主要是展示在WPF中使用ValidationRule自定义验证规则,同时展示两种错误响应方式。一种是通过Behavior传递到ViewModel中,然后进行错误信息响应;一种是直接在View中遍历当前也的所有错误元素,在页面中通过事件统一响应。1、自定义验证规则类这里自定义两个验证规则类,分别用于验证"用户名"输入不可为空、"邮箱"输入值需
e邮包:e邮包
墩煌网:墩煌网
eGenesis:eGenesis
DTDEX:DTDEX
"黑五"、"网一"狂欢将至,卖家怎么定价不亏本?怎么打折最赚钱?:"黑五"、"网一"狂欢将至,卖家怎么定价不亏本?怎么打折最赚钱?

没有评论:

发表评论