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,该类派生自,并实现了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" 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" Name="Label_MobilePhone" VerticalAlignment="Top" /> <TextBox Height="23" HorizontalAlignment="Right" Margin="0,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" Name="Button_ClickMe" VerticalAlignment="Top" Width="151" Click="ClickMe_Click" /> <Label Content="大侠,请留下你的联系方式,以备我能随时骚扰你!" Height="28" HorizontalAlignment="Left" Margin="32,19,0" Name="Label_Notice" VerticalAlignment="Top" Foreground="Red" /> <Label Content="Email:" Height="28" HorizontalAlignment="Left" Margin="32,156,0" Name="Label_Email" VerticalAlignment="Top" /> <TextBox Height="23" HorizontalAlignment="Left" Margin="100,159,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" Name="Label_HomePage" VerticalAlignment="Top" /> <TextBox Height="23" HorizontalAlignment="Left" Margin="100,209,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=newContactModel();”来设置的。
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()输出给用户。