WPF 資料繫結之ValidationRule資料校驗綜合Demo

【君莫笑】發表於2024-09-19

一、概述

我們利用ValidationRule以及ErrorTemplate來製作一個簡單的表單驗證。

二、Demo

核心思想:我們在ValidationRule中的Validate函式中進行驗證,然後將驗證結果存放至一個預先定義好的全域性資源中,這樣其他控制元件就可以根據驗證結果來進行相應的處理,程式碼參見以下:

   using System.ComponentModel;
   using System.Globalization;
   using System.Text.RegularExpressions;
   using System.Windows;
   using System.Windows.Controls;
   
   namespace BindingDemo5ValidationRuleDemo
   {
       /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
          private string nickName;
          public string NickName
          {
              get { return nickName; }
              set { nickName = value; }
          }
  
          private string phoneNumber;
          public string PhoneNumber
          {
              get { return phoneNumber; }
              set { phoneNumber = value; }
          }
  
          private string password;
          public string Password
          {
              get { return password; }
              set { password = value; }
          }
  
          private string confirmPassword;
          public string ConfirmPassword
          {
              get { return confirmPassword; }
              set { confirmPassword = value; }
          }
  
          public MainWindow()
          {
              InitializeComponent();
              this.DataContext = this;
          }
  
          private void Button_Click(object sender, RoutedEventArgs e)
          {
              MessageBox.Show(NickName);
          }
      }
  
      public class ValidationOutput : INotifyPropertyChanged
      {
          public event PropertyChangedEventHandler PropertyChanged;
          public void OnNotifyPropertyChanged(string propertyName)
          {
              if (PropertyChanged != null)
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
              }
          }
  
          private bool isAllValid = true;//Indicate if all elements is valid
  
          public bool IsAllValid
          {
              get { return isAllValid; }
              set { isAllValid = value;
                  OnNotifyPropertyChanged("IsAllValid");
              }
          }
  
  
          private string errorMsg4NickName;
          public string ErrorMsg4NickName
          {
              get { return errorMsg4NickName; }
              set
              {
                  errorMsg4NickName = value;
                  OnNotifyPropertyChanged("ErrorMsg4NickName");
              }
          }
  
          private bool isShow4NickName;
          public bool IsShow4NickName
          {
              get { return isShow4NickName; }
              set
              {
                  isShow4NickName = value;
                  OnNotifyPropertyChanged("IsShow4NickName");
              }
          }
  
  
          private string errorMsg4PhoneNumber;
         public string ErrorMsg4PhoneNumber
         {
             get { return errorMsg4PhoneNumber; }
             set
             {
                 errorMsg4PhoneNumber = value;
                 OnNotifyPropertyChanged("ErrorMsg4PhoneNumber");
             }
         }
 
         private bool isShow4PhoneNumber;
         public bool IsShow4PhoneNumber
         {
             get { return isShow4PhoneNumber; }
             set
             {
                 isShow4PhoneNumber = value;
                 OnNotifyPropertyChanged("IsShow4PhoneNumber");
             }
         }
 
         private bool isPhoneNumberValid;
         public bool IsPhoneNumberValid
         {
             get { return isPhoneNumberValid; }
             set
             {
                 isPhoneNumberValid = value;
                 OnNotifyPropertyChanged("IsPhoneNumberValid");
             }
         }
 
         private bool isNickNameValid;
         public bool IsNickNameValid
         {
             get { return isNickNameValid; }
             set
             {
                 isNickNameValid = value;
                 OnNotifyPropertyChanged("IsNickNameValid");
             }
         }
 
 
 
         private string errorMsg4Password;
         public string ErrorMsg4Password
         {
             get { return errorMsg4Password; }
             set
             {
                 errorMsg4Password = value;
                 OnNotifyPropertyChanged("ErrorMsg4Password");
             }
         }
 
         private bool isPasswordValid;
         public bool IsPasswordValid
         {
             get { return isPasswordValid; }
             set
             {
                 isPasswordValid = value;
                 OnNotifyPropertyChanged("IsPasswordValid");
             }
         }
 
         private string password;
         public string Password
         {
             get { return password; }
             set
             {
                 password = value;
                 OnNotifyPropertyChanged("Password");
             }
         }
 
 
         private string errorMsg4ConfirmPassword;
         public string ErrorMsg4ConfirmPassword
         {
             get { return errorMsg4ConfirmPassword; }
             set
             {
                 errorMsg4ConfirmPassword = value;
                 OnNotifyPropertyChanged("ErrorMsg4ConfirmPassword");
             }
         }
 
         private bool isConfirmPasswordValid;
         public bool IsConfirmPasswordValid
         {
             get { return isConfirmPasswordValid; }
             set
             {
                 isConfirmPasswordValid = value;
                 OnNotifyPropertyChanged("IsConfirmPasswordValid");
             }
         }
 
 
     }
 
     public class RegisterValidationRule : ValidationRule
     {
         private ValidationOutput validationOutput = null;
         public ValidationOutput ValidationOutput
         {
             get { return validationOutput; }
             set { validationOutput = value; }
         }
         private string validateType;
 
         public string ValidateType
         {
             get { return validateType; }
             set { validateType = value; }
         }
 
         public bool IsLegalPhoneNumber(string phoneNumber)
         {
             return Regex.IsMatch(phoneNumber, @"^1[3578]\d{9}$");
         }
         public override ValidationResult Validate(object value, CultureInfo cultureInfo)
         {
             if (ValidateType == "NickName")
             {
                 string s = (string)value;
                 if (s.Length < 6)
                 {
                     ValidationOutput.IsNickNameValid = false;
                     ValidationOutput.IsAllValid = false;
                     ValidationOutput.ErrorMsg4NickName = "Length should be longger than 6 characters";
                     return new ValidationResult(false, "Length should be longger than 6 characters");
                 }
                 else
                 {
                     ValidationOutput.IsNickNameValid = true;
                     ValidationOutput.IsAllValid = true;
                     return new ValidationResult(true, null);
                 }
            
             }
             else if(ValidateType == "PhoneNumber")
             {
                 string s = (string)value;
                 if (!IsLegalPhoneNumber(s))
                 {
                     //ValidationOutput.IsShow4PhoneNumber = true;
                     ValidationOutput.IsPhoneNumberValid = false;
                     ValidationOutput.IsAllValid = false;
                     ValidationOutput.ErrorMsg4PhoneNumber = "Phone number format is not correct";
                     return new ValidationResult(false, "Phone number format is not correct");
                 }
                 else
                 {
                     ValidationOutput.IsShow4PhoneNumber = false;
                     ValidationOutput.IsPhoneNumberValid = true;
                     ValidationOutput.IsAllValid = true;
                     return new ValidationResult(true, null);
                 }
             }
             else if (ValidateType == "Password")
             {
                 string myPassword = (string)value;
                 ValidationOutput.Password = myPassword;//Store the password in a global resource, used for validating the confirm password
                 if (myPassword.Length < 8)
                 {
                     ValidationOutput.IsPasswordValid = false;
                     ValidationOutput.IsAllValid = false;
                     ValidationOutput.ErrorMsg4Password = "Password length should be longger than 8 characters";
                     return new ValidationResult(false, "Password length should be longger than 8 characters");
                 }
                 else
                 {
                     ValidationOutput.IsPasswordValid = true;
                     ValidationOutput.IsAllValid = true;
                     return new ValidationResult(true, null);
                 }
             }
             else if (ValidateType == "ConfirmPassword")
             {
                 string myConfirmPassword = (string)value;
                 string myPassword = ValidationOutput.Password;
                 if (myPassword != myConfirmPassword)
                 {
                     ValidationOutput.IsConfirmPasswordValid = false;
                     ValidationOutput.IsAllValid = false;
                     ValidationOutput.ErrorMsg4ConfirmPassword = "Password are not the same";
                     return new ValidationResult(false, "Password are not the same");
                 }
                 else
                 {
                     ValidationOutput.IsConfirmPasswordValid = true;
                     ValidationOutput.IsAllValid = true;
                     return new ValidationResult(true, null);
                 }
             }
             return new ValidationResult(true, null);
 
         }
 
     }
 }
 <Window x:Class="BindingDemo5ValidationRuleDemo.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:BindingDemo5ValidationRuleDemo"
           mc:Ignorable="d"
           Title="RegisterWindow" Height="369.738" Width="479.098">
       <Window.Resources>
          <BooleanToVisibilityConverter x:Key="Bool2Visibility"/>
          <local:ValidationOutput x:Key="validateOutput" IsShow4NickName="False"></local:ValidationOutput>
          <ControlTemplate x:Key="validationTemplate">
              <DockPanel>
                  <AdornedElementPlaceholder Name="adorner"/>
                  <Grid Margin="20 0">
                      <Grid.ColumnDefinitions>
                          <ColumnDefinition Width="30"/>
                          <ColumnDefinition/>
                      </Grid.ColumnDefinitions>
                      <Ellipse Width="20" Height="20" Name="elps" Fill="Red"></Ellipse>
                      <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20" Foreground="White" Name="tbx"    Text="!"                         
                                 ToolTip="{Binding ElementName=adorner,  Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}" 
                      >
                      </TextBlock>
                  </Grid>
  
              </DockPanel>
          </ControlTemplate>
          <Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
              <Style.Triggers>
                  <Trigger Property="Validation.HasError" Value="true">
                      <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"/>
                      <Setter Property="BorderBrush" Value="Red"></Setter>
                      <Setter Property="BorderThickness" Value="2"></Setter>
                      <Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}" />
                  </Trigger>
              </Style.Triggers>
          </Style>
      </Window.Resources>
  
      <Border BorderThickness="1" BorderBrush="#FF1D3061" Margin="20">
          <Grid  >
              <Grid.RowDefinitions>
                  <RowDefinition Height="auto"/>
                  <RowDefinition Height="auto"/>
                  <RowDefinition Height="auto"/>
                  <RowDefinition Height="auto"/>
                  <RowDefinition Height="auto" MinHeight="79"/>
                  <RowDefinition/>
              </Grid.RowDefinitions>
              <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="141"/>
                  <ColumnDefinition Width="*"/>
                  <ColumnDefinition Width="100"/>
              </Grid.ColumnDefinitions>
              <TextBlock Text="暱  稱:" FontSize="20" VerticalAlignment="Center" Foreground="#FF416293" Margin="10,14" Height="28"></TextBlock>
              <TextBlock Text="電  話:" FontSize="20" VerticalAlignment="Center" Foreground="#FF416293" Margin="10,14" Grid.Row="1" Height="28"></TextBlock>
              <TextBlock Text="密  碼:" FontSize="20" VerticalAlignment="Center" Foreground="#FF416293" Margin="10,14" Grid.Row="2" Height="27"></TextBlock>
              <TextBlock Text="密  碼 確 認:" FontSize="20" VerticalAlignment="Center" Foreground="#FF416293" Margin="10,15" Grid.Row="3" Height="26"></TextBlock>
  
              <TextBox FontSize="20" VerticalAlignment="Center"  Margin="10,12" Grid.Column="1"  Style="{StaticResource textBoxInError}" Height="32" >
                  <TextBox.Text>
                      <Binding Path="NickName" UpdateSourceTrigger="PropertyChanged">
                          <Binding.ValidationRules>
                              <local:RegisterValidationRule ValidationOutput="{StaticResource validateOutput}" ValidateType="NickName"/>
                          </Binding.ValidationRules>
                      </Binding>
                  </TextBox.Text>
              </TextBox>
              <TextBox FontSize="20" VerticalAlignment="Center"  Margin="10,12" Grid.Column="1" Grid.Row="1" Name="tbxPhone" Style="{StaticResource textBoxInError}" Height="32"
              >
                  <TextBox.Text>
                      <Binding Path="PhoneNumber" UpdateSourceTrigger="PropertyChanged">
                          <Binding.ValidationRules>
                              <local:RegisterValidationRule ValidationOutput="{StaticResource validateOutput}" ValidateType="PhoneNumber"/>
                          </Binding.ValidationRules>
                      </Binding>
                  </TextBox.Text>
  
              </TextBox>
              <TextBox FontSize="20" VerticalAlignment="Center"  Margin="10,11" Grid.Column="1" Grid.Row="2"  Height="33" Style="{StaticResource textBoxInError}">
                  <TextBox.Text>
                      <Binding Path="Password" UpdateSourceTrigger="PropertyChanged">
                          <Binding.ValidationRules>
                              <local:RegisterValidationRule ValidationOutput="{StaticResource validateOutput}" ValidateType="Password"/>
                          </Binding.ValidationRules>
                      </Binding>
                  </TextBox.Text>
              </TextBox>
              <TextBox FontSize="20" VerticalAlignment="Center"  Margin="10,11" Grid.Column="1" Grid.Row="3"  Height="34" Style="{StaticResource textBoxInError}">
                  <TextBox.Text>
                      <Binding Path="ConfirmPassword" UpdateSourceTrigger="PropertyChanged">
                          <Binding.ValidationRules>
                              <local:RegisterValidationRule ValidationOutput="{StaticResource validateOutput}" ValidateType="ConfirmPassword"/>
                          </Binding.ValidationRules>
                      </Binding>
                  </TextBox.Text>
              </TextBox>
              <Button Grid.Row="4" Grid.Column="2" Margin="8,18,8,14" Content="註冊" Background="#FF2C6CA2" Foreground="White" Click="Button_Click"
                     IsEnabled="{Binding Path=IsAllValid, Source={StaticResource validateOutput}}"></Button>
 
             <Grid Grid.Column="2" Margin="10,10" Visibility="{Binding Path=IsNickNameValid, Source={StaticResource validateOutput}, Converter={StaticResource Bool2Visibility}}">
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="30"/>
                     <ColumnDefinition/>
                 </Grid.ColumnDefinitions>
                 <Ellipse Width="20" Height="20" Fill="Green"></Ellipse>
                 <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="White">√</TextBlock>
                 <!--<TextBlock VerticalAlignment="Center"  FontSize="20" Foreground="Red" Grid.Column="1" 
                            Text="{Binding Path=ErrorMsg4NickName, Source={StaticResource validateOutput}}"
                       >
 
                 </TextBlock>-->
             </Grid>
 
             <Grid Grid.Column="2" Grid.Row="1" Margin="10,10" Visibility="{Binding Path=IsPhoneNumberValid, Source={StaticResource validateOutput}, Converter={StaticResource Bool2Visibility}}">
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="30"/>
                     <ColumnDefinition/>
                 </Grid.ColumnDefinitions>
                 <Ellipse Width="20" Height="20" Fill="Green"></Ellipse>
                 <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="White">√</TextBlock>
             </Grid>
 
             <Grid Grid.Column="2" Grid.Row="2" Margin="10,10" Visibility="{Binding Path=IsPasswordValid, Source={StaticResource validateOutput}, Converter={StaticResource Bool2Visibility}}">
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="30"/>
                     <ColumnDefinition/>
                 </Grid.ColumnDefinitions>
                 <Ellipse Width="20" Height="20" Fill="Green"></Ellipse>
                 <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="White">√</TextBlock>
             </Grid>
 
             <Grid Grid.Column="2" Grid.Row="3" Margin="10,10" Visibility="{Binding Path=IsConfirmPasswordValid, Source={StaticResource validateOutput}, Converter={StaticResource Bool2Visibility}}">
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="30"/>
                     <ColumnDefinition/>
                 </Grid.ColumnDefinitions>
                 <Ellipse Width="20" Height="20" Fill="Green"></Ellipse>
                 <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="White">√</TextBlock>
             </Grid>
         </Grid>
     </Border>
 </Window>

來源:https://www.cnblogs.com/3xiaolonglong/p/9781015.html

相關文章