WPF中使用ValidationRule自定義驗證規則
本文主要是展示在 WPF 中使用 ValidationRule 自定義驗證規則,然后通過 Behavior 傳遞到 ViewModel 中,在 ViewModel 中對錯誤資訊統一回應,
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、在前端頁面中添加驗證
在前端頁面中需要進行以下操作:
-
添加自定義的 ValidationRule 所有的命名空間;
xmlns:valRules="clr-namespace:MyValidationRuleDemo.MyValidationRules" -
在需要驗證的控制元件上的 Binding 上對應的自定義驗證規則類;
<Binding.ValidationRules> <valRules:EmailValidationRule /> </Binding.ValidationRules>
具體代碼如下:
<Window
x:
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:MyValidationRuleDemo"
xmlns:valRules="clr-namespace:MyValidationRuleDemo.MyValidationRules"
Title="MainWindow"
Width="800"
Height="400"
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 Width="200" Height="30">
<TextBox.Text>
<Binding
Path="UserName"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<valRules:NotEmptyValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
<StackPanel Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<Label
Content="郵箱:"
Margin="0,0,10,0"
FontSize="20" />
<TextBox Width="200" Height="30">
<TextBox.Text>
<Binding
Path="UserEmail"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<valRules:EmailValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
<Button Grid.Row="2"
Content="提交"
Width="200"
Height="30"
Margin="0,20,0,0" />
</Grid>
</Window>
前端頁面系結的驗證引數具體如下:
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 中默認的效果,效果如下圖:

3、使用 Behavior 自定義回應效果
上面雖然已經在頁面上有了基本的錯誤回應效果,但是效果過于單一,這里我們在這里使用 Behavior 監聽 Validation.Error 事件,并將錯誤資訊傳遞到 ViewModel 中進行統一進行錯誤提醒,同時,在 MVMM 架構中將錯誤資訊傳遞到 ViewModel 中進行統一處理,在有需要的時候也有利于業務邏輯處理,
3.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> -
通過自定義的 ValidationExceptionBehavior 繼承于 Behavior,用于監聽 Validation.Error 的錯誤事件,
protected override void OnAttached() { //添加 Validation.Error 事件監聽 this.AssociatedObject.AddHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(OnValidationError)); } -
View 中添加 Behavior;
<i:Interaction.Behaviors> <local:ValidationExceptionBehavior /> </i:Interaction.Behaviors> -
在 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()); } } -
在 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()); }); } -
開啟 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:
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:MyValidationRuleDemo"
xmlns:valRules="clr-namespace:MyValidationRuleDemo.MyValidationRules"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow"
Width="800"
Height="400"
mc:Ignorable="d">
<i:Interaction.Behaviors>
<local:ValidationExceptionBehavior />
</i:Interaction.Behaviors>
<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 Width="200" Height="30">
<TextBox.Text>
<Binding
Path="UserName"
NotifyOnValidationError="True"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<valRules:NotEmptyValidationRule ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
<StackPanel Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<Label
Content="郵箱:"
Margin="0,0,10,0"
FontSize="20" />
<TextBox Width="200" Height="30">
<TextBox.Text>
<Binding
Path="UserEmail"
NotifyOnValidationError="True"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<valRules:EmailValidationRule ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
<Button Grid.Row="2"
Content="提交"
Command="{Binding SaveCommand}"
Width="200"
Height="30"
Margin="0,20,0,0" />
</Grid>
</Window>
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、效果展示

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/256586.html
標籤:WPF
