1 新建WPF应用程序ValidationRuleExp
整个程序的结构如下图所示。
程序运行起来后的效果如下图所示。
用户操作程序时,先输入固话、手机、Email、个人网站等信息,再点击右侧的“点我记住你”按钮,便可以保存用户输入的信息。
2 新建业务实体类ContactModel(类文件为ContactModel.cs)
ContactModel类包含固话、手机、Email、个人网站等属性,分别与界面的固话文本框、手机文本框、Email文本框、个人网站文本框绑定。ContactModel类实现INotifyPropertyChanged接口,这样一来,当ContactModel类的某一属性发生改变时,便可以向执行绑定的客户端发出某一属性值已更改的通知。例如:将ContactModel类的TelePhone属性与客户端的“固话”文本框进行绑定,一旦TelePhone属性的值发生改变,将会通知“固话”文本框更新自己的值。
详细代码如下所示。
//************************************************************
//
// ValidationRule类示例代码
//
// Author:三五月儿
//
// Date:2014/07/11
//
// http://blog.csdn.net/yl2isoft
//
//************************************************************
using System.ComponentModel;
namespace ValidationRuleExp
{
public class ContactModel : INotifyPropertyChanged
{
/// <summary>
/// 固话号码
/// </summary>
private string telePhone;
public string TelePhone
{
get
{
return telePhone;
}
set
{
telePhone = value;
NotifyPropertyChanged("TelePhone");
}
}
/// <summary>
/// 手机号码
/// </summary>
private string mobilePhone;
public string MobilePhone
{
get
{
return mobilePhone;
}
set
{
mobilePhone = value;
NotifyPropertyChanged("MobilePhone");
}
}
/// <summary>
/// 电子邮件地址
/// </summary>
private string email;
public string Email
{
get
{
return email;
}
set
{
email = value;
NotifyPropertyChanged("Email");
}
}
/// <summary>
/// 个人网站地址
/// </summary>
private string homePage;
public string HomePage
{
get
{
return homePage;
}
set
{
homePage = value;
NotifyPropertyChanged("HomePage");
}
}
/// <summary>
/// NotifyPropertyChanged事件
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
3 新建自定义的规则类ContactRule,该类继承自ValidationRule类
当应用使用WPF数据绑定模型时,可以将规则集合ValidationRules与绑定关联。这样一来,当绑定对象的绑定值发生改变时,则绑定引擎就会检查ValidationRule,确认绑定对象的值是否通过了ValidationRule类指定的验证规则。若成功通过验证,则调用属性的set方法为属性赋值;若未通过验证,则会给出提示,同时中止属性赋值操作。
这里的规则集合ValidationRules可以包含一个或多个ValidationRule对象。ValidationRule对象的类型可以是派生自ValidationRule类的自定义类,也可以是内置的ExceptionValidationRule类。本例中使用自定义的规则类ContactRule,该类派生自ValidationRule,并实现了Validate方法,Validate方法中对用户的输入进行验证,这里的数据验证主要是借助于正则表达式来完成的。
另外,我们自定义的ContactRule类,还接受一个输入参数checkType,该参数可以告知ContactRule类需要验证的对象的类型,0代表固话,1代表手机,2代表Email,3代表个人网站。
下面给出ContactRule类的完整代码。
//************************************************************
//
// ValidationRule类示例代码
//
// Author:三五月儿
//
// Date:2014/07/11
//
// http://blog.csdn.net/yl2isoft
//
//************************************************************
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows.Controls;
namespace ValidationRuleExp
{
public class ContactRule :ValidationRule
{
public int checkType { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
try
{
if (checkType == 0)
{//固话
if (value == null || string.IsNullOrEmpty(value.ToString().Trim()) || !IsTelePhone(value.ToString().Trim()))
{
return new ValidationResult(false, "大侠,你输入的固话号码有误!");
}
}
else if (checkType == 1)
{//手机
if (value == null || string.IsNullOrEmpty(value.ToString().Trim()) || !IsMobilePhone(value.ToString().Trim()))
{
return new ValidationResult(false, "大侠,你输入的手机号码有误!");
}
}
else if (checkType == 2)
{//Email
if (value == null || string.IsNullOrEmpty(value.ToString().Trim()) || !IsEmail(value.ToString().Trim()))
{
return new ValidationResult(false, "大侠,你输入的Email有误!");
}
}
else
{//HomePage
if (value == null || string.IsNullOrEmpty(value.ToString().Trim()) || !IsHomePage(value.ToString().Trim()))
{
return new ValidationResult(false, "大侠,你输入的个人网址有误!");
}
}
return new ValidationResult(true, null);
}
catch (Exception e)
{
return new ValidationResult(false, e.Message);
}
}
private bool IsTelePhone(string telePhone)
{
return Regex.IsMatch(telePhone, @"^(\d{3,4}-)?\d{6,8}$");
}
private bool IsMobilePhone(string mobilePhone)
{
return Regex.IsMatch(mobilePhone, @"^[1]([3][0-9]{1}|59|58|88|89)[0-9]{8}$");
}
private bool IsEmail(string email)
{
return Regex.IsMatch(email, @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
}
private bool IsHomePage(string email)
{
return Regex.IsMatch(email, @"http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?");
}
}
}
4 编写程序画面代码
程序的主画面如下图所示。
画面中用到的主要控件如下表所示。
项号 | 控件类型 | 控件名称 | 绑定属性 | 说明 |
1 | TextBox | TextBox_TelePhone | TelePhone | 固话号码 |
2 | TextBox | TextBox_MobilePhone | MobilePhone | 手机号码 |
3 | TextBox | TextBox_Email | | 邮箱地址 |
4 | TextBox | TextBox_HomePage | HomePage | 个人网站地址 |
5 | Button | Button_ClickMe | - | 保存用户输入信息 |
下面是程序主画面的完整代码。
(1)MainWindow.xaml
<Window x:Class="ValidationRuleExp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cr="clr-namespace:ValidationRuleExp"
Title="MainWindow" Height="300" Width="500" ResizeMode="NoResize">
<Grid>
<Label Content="固话:" Height="28" HorizontalAlignment="Left" Margin="32,69,0,0" Name="Label_TelePhone" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Right" Margin="0,71,228,0" Name="TextBox_TelePhone" VerticalAlignment="Top" Width="168" >
<TextBox.Text>
<Binding Path="TelePhone">
<Binding.ValidationRules>
<cr:ContactRule checkType="0"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Label Content="手机:" Height="28" HorizontalAlignment="Left" Margin="32,109,0,0" Name="Label_MobilePhone" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Right" Margin="0,109,228,0" Name="TextBox_MobilePhone" VerticalAlignment="Top" Width="168" >
<TextBox.Text>
<Binding Path="MobilePhone">
<Binding.ValidationRules>
<cr:ContactRule checkType="1"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="点我记住你!!!" Height="69" HorizontalAlignment="Left" Margin="295,81,0,0" Name="Button_ClickMe" VerticalAlignment="Top" Width="151" Click="ClickMe_Click" />
<Label Content="大侠,请留下你的联系方式,以备我能随时骚扰你!" Height="28" HorizontalAlignment="Left" Margin="32,19,0,0" Name="Label_Notice" VerticalAlignment="Top" Foreground="Red" />
<Label Content="Email:" Height="28" HorizontalAlignment="Left" Margin="32,156,0,0" Name="Label_Email" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="100,159,0,0" Name="TextBox_Email" VerticalAlignment="Top" Width="166" >
<TextBox.Text>
<Binding Path="Email">
<Binding.ValidationRules>
<cr:ContactRule checkType="2"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Label Content="个人网站:" Height="28" HorizontalAlignment="Left" Margin="32,206,0,0" Name="Label_HomePage" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="100,209,0,0" Name="TextBox_HomePage" VerticalAlignment="Top" Width="342" >
<TextBox.Text>
<Binding Path="HomePage">
<Binding.ValidationRules>
<cr:ContactRule checkType="3"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</Window>
(2)MainWindow.xaml.cs
//************************************************************
//
// ValidationRule类示例代码
//
// Author:三五月儿
//
// Date:2014/07/11
//
// http://blog.csdn.net/yl2isoft
//
//************************************************************
using System.Windows;
using System.Windows.Controls;
namespace ValidationRuleExp
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ContactModel();
Contact.TelePhone = "010-22222222";
Contact.MobilePhone = "15888888888";
Contact.Email = "864003248@qq.com";
Contact.HomePage = "http://blog.csdn.net/yl2isoft";
}
//注意:此处省去了输入文本为空的校验
public bool IsValidInput()
{
if (!CheckInput(this.TextBox_TelePhone)
|| !CheckInput(this.TextBox_MobilePhone)
|| !CheckInput(this.TextBox_Email)
|| !CheckInput(this.TextBox_HomePage))
{
return false;
}
return true;
}
private bool CheckInput(TextBox input)
{
if (System.Windows.Controls.Validation.GetHasError(input))
{
MessageBox.Show(System.Windows.Controls.Validation.GetErrors(input)[0].ErrorContent.ToString());
return false;
}
return true;
}
private void ClickMe_Click(object sender, RoutedEventArgs e)
{
if (IsValidInput())
{
MessageBox.Show("大侠,我记住你了!");
}
}
}
}
MainWindow.xaml文件中的以下代码与数据验证有关(此处以TextBox_TelePhone文本框为例),所以下面将此部分代码特别提取出来进行重点说明。
<TextBox.Text>
<Binding Path="TelePhone">
<Binding.ValidationRules>
<cr:ContactRule checkType="0"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
针对这段代码,做以下几点说明:
1)
Binding.Path="TelePhone"
通过此句代码可以设置绑定的源属性,将源对象的TelePhone属性绑定给目标对象的Text属性。本例中的源对象为ContactModel实例,目标对象为文本框TextBox_TelePhone。源对象是通过MainWindow.xaml.cs文件中的代码“this.DataContext = new ContactModel();”来设置的。
2)
<Binding.ValidationRules>
<cr:ContactRule checkType="0"/>
</Binding.ValidationRules>
代码中,使用Binding.ValidationRules将用来检查用户输入的规则集合ValidationRules与Binding对象相关联,将规则集合ValidationRules与Binding对象关联后,当用户的输入没有通过验证时,会在文本框的周围生成红色轮廓,以此来告知用户,该输入是不合法的。
3)
<cr:ContactRule checkType="0"/>
针对这句代码,再来啰嗦几句。
MainWindow.xaml文件一开始,使用代码xmlns:cr="clr-namespace:ValidationRuleExp"导入命名空间ValidationRuleExp,进而可以使用cr:ContactRule的方式来访问命名空间ValidationRuleExp中的ContactRule类了。
下面再来对MainWindow.xaml.cs文件中的代码进行说明。
点击画面按钮,执行ClickMe_Click()方法,方法中会调用IsValidInput()方法对用户输入进行验证,当用户输入的信息中存在错误时,会弹出错误信息提示框,否则,弹出“大侠,我记住你了!”的提示框(以此来模拟保存用户信息的操作)。
针对MainWindow.xaml.cs文件中的代码,重点说明以下几点:
1)使用System.Windows.Controls.Validation.GetHasError(input)来检查控件内容是否有误?
System.Windows.Controls.Validation.GetHasError()方法可以用来获取指定元素的附加属性HasError的值,HasError属性保存bool类型的值,当HasError的值为true时,说明指定元素的绑定存在验证错误,否则为 false。本例中使用该方法来检查文本框是否存在验证错误,若有误,则使用MessageBox.Show()方法输出错误信息。
2)使用System.Windows.Controls.Validation.GetErrors(input)[0].ErrorContent.ToString()来获取验证错误信息。
System.Windows.Controls.Validation.GetErrors()方法可以获取指定元素的附加属性Errors的值。 通过访问附加属性Errors,可以获取与绑定相关联的 ValidationError对象的集合。ValidationError 则保存由绑定引擎产生的验证错误。
3)验证未通过的条件为什么要这样写?
if (!CheckInput(this.TextBox_TelePhone) || !CheckInput(this.TextBox_MobilePhone) || !CheckInput(this.TextBox_Email) || !CheckInput(this.TextBox_HomePage)){
return false;
}
这样写可以确保就算有多个文本框存在验证错误时,也只会将第一个文本框的错误信息被弹出。
5 最后的总结
1)对用户输入的验证是在属性的set方法被执行前进行的,所以当用户的输入没有通过验证时,是不会触发属性的set方法的。
2)验证未通过时,给用户的唯一提示就是产生红框,要想弹出错误消息,需要借助System.Windows.Controls.Validation.GetErrors(input)[0].ErrorContent.ToString()来获取错误信息并使用MessageBox.Show()输出给用户。