通常我們都會針對應用程式中的文字輸入欄位做一些檢核或是驗證的動作,如果要驗證的欄位有透過DataBinding來做存取值的話,可以透過BindingValidation相關功能進行資料驗證的動作;但是,如果要驗證的欄位完全沒有做DataBinding的話怎麼辦呢!?
既然沒有自動的方法,那我們就自己來手工打造一個自訂的驗證機制吧!!
通常我們都會針對應用程式中的文字輸入欄位做一些檢核或是驗證的動作,如果要驗證的欄位有透過DataBinding來做存取值的話,可以透過BindingValidation相關功能進行資料驗證的動作;但是,如果要驗證的欄位完全沒有做DataBinding的話怎麼辦呢!?
既然沒有自動的方法,那我們就自己來手工打造一個自訂的驗證機制吧!!
首先,我們需要在專案中加入System.ComponentModel.DataAnnotations的參考。
接著專案中加入一個名為CustomValidation的Class,內容如下:
public class CustomValidation
{
private string _message;
public CustomValidation( string message )
{
this._message = message;
}
public bool ShowErrorMessage
{
get;
set;
}
public object ValidationError
{
get
{
return null;
}
set
{
if( ShowErrorMessage )
{
throw new ValidationException( _message );
}
}
}
}
再來我們要利用C# 3.0新增的功能Extension Method來為FrameworkElement植入可以做驗證的功能,並且透過Tag這個Property來當作媒介,傳遞一個用來驗證的Binding物件,建立一個名為FrameworkElementExtension的Class:
public static class FrameworkElementExtension
{
public static void SetValidation( this FrameworkElement frameworkElement , string message )
{
CustomValidation customValidation = new CustomValidation( message );
Binding binding = new Binding( "ValidationError" )
{
Mode = System.Windows.Data.BindingMode.TwoWay ,
NotifyOnValidationError = true ,
ValidatesOnExceptions = true ,
Source = customValidation
};
frameworkElement.SetBinding( Control.TagProperty , binding );
}
public static void RaiseValidationError( this FrameworkElement frameworkElement )
{
BindingExpression bindingExpression = frameworkElement.GetBindingExpression( Control.TagProperty );
if( bindingExpression != null )
{
( ( CustomValidation ) bindingExpression.DataItem ).ShowErrorMessage = true;
bindingExpression.UpdateSource();
}
}
public static void ClearValidationError( this FrameworkElement frameworkElement )
{
BindingExpression bindingExpression = frameworkElement.GetBindingExpression( Control.TagProperty );
if( bindingExpression != null )
{
( ( CustomValidation ) bindingExpression.DataItem ).ShowErrorMessage = false;
bindingExpression.UpdateSource();
}
}
public static bool IsPlainTextValid( this string inputText )
{
bool isTextValid = true;
foreach( char character in inputText )
{
if( char.IsWhiteSpace( character ) != true )
{
if( char.IsLetterOrDigit( character ) != true )
{
if( CharUnicodeInfo.GetUnicodeCategory( character ) != UnicodeCategory.NonSpacingMark )
{
isTextValid = false;
break;
}
}
}
}
return isTextValid;
}
public static bool IsNumberValid( this string inputNumber )
{
bool isNumberValid = true;
int number = -1;
if( Int32.TryParse( inputNumber , out number ) != true )
{
isNumberValid = false;
}
return isNumberValid;
}
public static bool IsEmailValid( this string inputEmail )
{
bool isEmailValid = true;
string emailExpression = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$";
Regex regex = new Regex( emailExpression );
if( regex.IsMatch( inputEmail ) != true )
{
isEmailValid = false;
}
return isEmailValid;
}
}
仔細看看程式碼就會發現,我已經在裡面多放了三個用來做驗證三種不同資料格式用的Method了,如果有需要加入其他的驗證規則,也可以依照這個模式繼續往下加。
到這邊,前置工作就完成了,再來就可以開始利用剛剛寫好的東西來對欄位進行驗證了,這邊提供我隨便做的小範例:
<UserControl x:Class="SL_CustomValidation.MainPage"
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"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">
<Grid x:Name="LayoutRoot" Background="Transparent" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<Viewbox>
<TextBlock Text="自訂欄位驗證" Foreground="LightGray" FontStyle="Italic" FontStretch="Normal" />
</Viewbox>
<Viewbox Grid.Row="1">
<TextBlock Text="只限輸入整數" Foreground="LightGray" FontStyle="Italic" FontStretch="Normal" />
</Viewbox>
<TextBox Grid.Row="1" Name="txtIntegerField" Width="200" Height="32" HorizontalAlignment="Right" Margin="10" Background="#80FFFFFF"/>
<Viewbox Grid.Row="2">
<TextBlock Text="只限輸入Email格式" Foreground="LightGray" FontStyle="Italic" FontStretch="Normal" />
</Viewbox>
<TextBox Grid.Row="2" Name="txtEmailField" Width="200" Height="32" HorizontalAlignment="Right" Margin="10" Background="#80FFFFFF"/>
<Viewbox Grid.Row="3">
<TextBlock Text="只接受一般文字字元" Foreground="LightGray" FontStyle="Italic" FontStretch="Normal" />
</Viewbox>
<TextBox Grid.Row="3" Name="txtPlainTextField" Width="200" Height="32" HorizontalAlignment="Right" Margin="10" Background="#80FFFFFF"/>
<Button Grid.Row="4" Width="100" Name="btnValidate" Margin="5" Click="btnValidate_Click">
<TextBlock Text="進行驗證" FontSize="14" />
</Button>
</Grid>
</UserControl>
using System.Windows;
using System.Windows.Controls;
namespace SL_CustomValidation
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void btnValidate_Click( object sender , RoutedEventArgs e )
{
bool isPassedValidation = true;
txtIntegerField.ClearValidationError();
txtEmailField.ClearValidationError();
txtPlainTextField.ClearValidationError();
if( string.IsNullOrEmpty( txtIntegerField.Text ) || txtIntegerField.Text.IsNumberValid() == false )
{
txtIntegerField.SetValidation( "請輸入合法的整數" );
txtIntegerField.RaiseValidationError();
isPassedValidation = false;
}
if( string.IsNullOrEmpty( txtEmailField.Text ) || txtEmailField.Text.IsEmailValid() == false )
{
txtEmailField.SetValidation( "請輸入合法的Email信箱格式" );
txtEmailField.RaiseValidationError();
isPassedValidation = false;
}
if( string.IsNullOrEmpty( txtPlainTextField.Text ) || txtPlainTextField.Text.IsPlainTextValid() == false )
{
txtPlainTextField.SetValidation( "請輸入不包含任何符號的文字" );
txtPlainTextField.RaiseValidationError();
isPassedValidation = false;
}
if( isPassedValidation == true )
{
MessageBox.Show( "通過驗證!!" );
}
}
}
}
來看看成果吧!!
最後的最後,附上原始碼,請自行服用~