1、ValidationRule 验证

ValidationRule:是通过ValidationRule中的的Validate方法来验证我们绑定的属性。所以我们的用法是继承ValidationRule,重写他的Validate方法。示例

public class RequiredRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value == null)
return new ValidationResult(false, "不能为空值!");
if (string.IsNullOrEmpty(value.ToString()))
return new ValidationResult(false, "不能为空字符串!"); return new ValidationResult(true, null);
}
}

而XAML中需要把错误信息显示出来。

<Window.Resources>
<ControlTemplate x:Key="ErrorTemplate">
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder/>
</Border>
</ControlTemplate>
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}">
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Text="姓名"/>
<TextBox>
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ValidationRules:RequiredRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text="年龄"/>
<TextBox >
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ValidationRules:GreaterThanRule Number="10"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>

这样显示的错误信息就会以 ToolTip和红色边框的形式显示出来。但这边如果又在TextBox里面设置ToolTip那么就会优先选择TextBox里的,也就是Style中的ToolTip遇到错误信息是不会显示出来的,而是显示TextBox中的ToolTip。所以我们可以改善一下显示的模版来解决这个问题。

<ControlTemplate x:Key="ErrorTemplate">
<DockPanel LastChildFill="true">
<Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
</TextBlock>
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>

2、Exception 验证

Exception :我们xaml中绑定的对象是属性。所以Exception验证,就是通过属性的改变来判断是否正常。如:

 public int Age
{
get { return _age; }
set
{
if (value > 200)
{
throw new Exception("年龄不能大于200");
}
_age = value;
}
}

同样跑出的异常在Xaml中也要显示下。XAML同上。这种方式就会破坏POCO的设计原则。

3、IDataErrorInfo 验证

IDataErrorInfo:这个验证是通过我们的实体对象继承IDataErrorInfo来实现的。这里声明的this索引器来访问类的成员。

 public class BaseDataErrorInfo : IDataErrorInfo
{
private string _error; public string this[string columnName]
{
get { return GetErrorFor(columnName); }
} public string Error
{
get { return _error; }
set { _error = value; }
} public virtual string GetErrorFor(string columnName)
{
return string.Empty;
}
}
public class Person : BaseDataErrorInfo
{
public string Name { get; set; } public override string GetErrorFor(string columnName)
{
if (columnName == "Name")
if (string.IsNullOrEmpty(Name))
return "Name 不能为空"; return base.GetErrorFor(columnName);
} }

XAML同上。

4、Custom Control 验证

这里我即不想污染实体类,又想实现一个通用的Validate。我想通过我xaml绑定的属性和它所属的控件。来显示ToolTip。

  public abstract class Validator : FrameworkElement
{
static Validator()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Validator), new FrameworkPropertyMetadata(typeof(Validator)));
} public virtual string ErrorMessage { get { return string.Empty; } }
public abstract bool InitialValidation();
public FrameworkElement ElementName
{
get { return (FrameworkElement)GetValue(ElementNameProperty); }
set { SetValue(ElementNameProperty, value); }
} // Using a DependencyProperty as the backing store for ElementName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ElementNameProperty =
DependencyProperty.Register("ElementName", typeof(FrameworkElement), typeof(Validator), new PropertyMetadata(null)); public object Source
{
get { return (object)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
} // Using a DependencyProperty as the backing store for Source. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(object), typeof(Validator), new UIPropertyMetadata(new PropertyChangedCallback(ValidPropertyPropertyChanged))); private static void ValidPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var validator = d as Validator;
if (validator != null)
validator.SetSourceFromProperty();
if (string.IsNullOrEmpty(e.NewValue.ToString()))
{
if (validator != null)
{
validator.IsValid = validator.InitialValidation();
if (validator.ElementName.DataContext != null)
validator.ShowToolTip();
validator.IsValid = false;
}
}
} private void ShowToolTip()
{
if (IsValid)
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1.5);
_toolTip = new ToolTip();
_toolTip.StaysOpen = true;
_toolTip.PlacementTarget = ElementName;
_toolTip.Placement = PlacementMode.Right; _toolTip.Content = ErrorMessage;
_toolTip.IsOpen = true;
timer.Tick += (sender, args) =>
{
_toolTip.IsOpen = false;
timer.Stop();
};
timer.Start();
} }
private void SetSourceFromProperty()
{
var expression = this.GetBindingExpression(SourceProperty);
if (expression != null && this.ElementName == null)
this.SetValue(Validator.ElementNameProperty, expression.DataItem as FrameworkElement); } private ToolTip _toolTip;
private DispatcherTimer timer; public bool IsValid { get; set; }
}

这是一个简单的Validate基类。提供思想。功能不完善。

然后继承这个Validator

public class RequiredValidator : Validator
{
public override string ErrorMessage { get { return "不能为空值"; } }
public override bool InitialValidation()
{
if (Source == null)
return false;
return string.IsNullOrEmpty(Source.ToString());
}
}

这里ErrorMessage是显示错误信息。

InitialValidation方法是我们要验证的规则。

代码

关于使用的小例子:

一、通过代码实现数据绑定

通过代码实现数据绑定,使用的是System.Windows.Data命名空间的Binding类,主要使用Binding类的如下的属性:

  • Source属性:绑定到的数据源
  • Mode属性:绑定的模式(OneTime、OneWay、TwoWay、OneWayToSource或Default)
  • Path属性:绑定到的数据源的属性
  • Converter属性:绑定时所使用的类型转换器

在绑定目标控件上使用SetBinding方法添加数据绑定。例如将MyData的Name属性绑定到txtName控件的Text属性上,使用MyColorConverter转换器将MyBindingColor的ColorObject属性绑定到rec控件的Fill属性上:

   1: MyData data = new MyData();
   2:  
   3: Binding binding1 = new Binding();
   4: binding1.Source = data;
   5: binding1.Mode = BindingMode.OneWay;
   6: binding1.Path = new PropertyPath("Name");
   7:  
   8: txtName.SetBinding(TextBox.TextProperty, binding1);
   9:  
  10:  
  11: MyBindingColor color = new MyBindingColor();
  12:  
  13: Binding binding2 = new Binding();
  14: binding2.Source = color;
  15: binding2.Mode = BindingMode.OneWay;
  16: binding2.Path = new PropertyPath("ColorObject");
  17: binding2.Converter = new MyColorConverter();
  18:  
  19: rec.SetBinding(Rectangle.FillProperty, binding2);

二、实现绑定数据的验证:

对于绑定数据的验证,系统采用如下的机制:

使用 WPF 数据绑定模型可以将 ValidationRules 与 Binding 对象相关联。当绑定目标的属性向绑定源属性传递属性值时(仅限TwoWay模式或OneWayToSource模式),执行ValidationRule中的Validate方法,实现对界面输入数据的验证。

定义验证可以采用以下三种:

  • DataErrorValidationRule:检查由源对象的 IDataErrorInfo 实现所引发的错误,要求数据源对象实现System.ComponentModel命名空间的IDataErrorInfo接口。

例如,定义一个学生信息类,要求其学生成绩在0到100间,学生姓名的长度在2到10个字符间:

   1: public class StudentInfoWithValidation : IDataErrorInfo
   2: {
   3:     #region 构造方法
   4:     public StudentInfoWithValidation()
   5:     {
   6:         StudentName = "Tom";
   7:         Score = 90;
   8:     }
   9:     public StudentInfoWithValidation(string m_StudentName,double m_Score)
  10:     {
  11:         StudentName = m_StudentName;
  12:         Score = m_Score;
  13:     }
  14:     #endregion
  15:  
  16:     #region 属性
  17:     public string StudentName
  18:     {
  19:         get; set;
  20:     }
  21:     public double Score
  22:     {
  23:         get; set;
  24:     }
  25:     #endregion
  26:  
  27:     #region 实现IDataErrorInfo接口的成员
  28:     public string Error
  29:     {
  30:         get 
  31:         {
  32:             return null;
  33:         }
  34:     }
  35:  
  36:     public string this[string columnName]
  37:     {
  38:         get
  39:         {
  40:             string result = null;
  41:  
  42:             switch (columnName)
  43:             {
  44:                 case "StudentName":
  45:                     // 设置StudentName属性的验证规则
  46:                     int len = StudentName.Length;
  47:                     if (len < 2 || len > 10)
  48:                     {
  49:                         result = "StudentName length must between 2 and 10";
  50:                     }
  51:                     break;
  52:                 case "Score":
  53:                     // 设置Score属性的验证规则
  54:                     if (Score < 0 || Score > 100)
  55:                     {
  56:                         result = "Score must between 0 and 100";
  57:                     }
  58:                     break;
  59:             }
  60:  
  61:             return result;
  62:         }
  63:     }
  64:     #endregion
  65: }

在界面上,定义两个TextBox绑定到StudentName和Score两个属性上,并设置其采用DataErrorValidationRule:

   1: <Window x:Class="WPFDataBindingDemo.WinDataErrorValidationRuleDemo"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:WPFDataBindingDemo"
   5:     Title="WinDataErrorValidationRuleDemo" Height="154" Width="300">
   6:     <Canvas Height="116" x:Name="mainCanvas">
   7:         <Canvas.Resources>
   8:             <local:StudentInfoWithValidation x:Key="myData" />
   9:         </Canvas.Resources>
  10:         <Canvas.DataContext>
  11:             <Binding Source="{StaticResource myData}" />
  12:         </Canvas.DataContext>
  13:         <Label Canvas.Left="10" Canvas.Top="10" Height="28" Name="label1" Width="120">StudentName:</Label>
  14:         <Label Canvas.Left="10" Canvas.Top="36" Height="28" Name="label2" Width="120">Score:</Label>
  15:         <TextBox Canvas.Left="136" Canvas.Top="12" Height="23" Name="textBox1" Width="120">
  16:             <TextBox.Text>
  17:                 <Binding Path="StudentName" 
  18:                          Mode="TwoWay" 
  19:                          UpdateSourceTrigger="PropertyChanged"
  20:                          ValidatesOnDataErrors="True" />
  21:             </TextBox.Text>
  22:         </TextBox>
  23:         <TextBox Canvas.Left="136" Canvas.Top="41" Height="23" Name="textBox2" Width="120">
  24:             <TextBox.Text>
  25:                 <Binding Path="Score" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
  26:                     <!--与上一个TextBox控件的写法作用相同-->
  27:                     <Binding.ValidationRules>
  28:                         <DataErrorValidationRule />
  29:                     </Binding.ValidationRules>
  30:                 </Binding>
  31:             </TextBox.Text>
  32:         </TextBox>
  33:         <Button Canvas.Left="12" Canvas.Top="79" Height="23" Name="button1" Width="118" Click="button1_Click">Get Student Info</Button>
  34:         <Button Canvas.Left="136" Canvas.Top="79" Height="23" Name="button2" Width="118" Click="button2_Click">Get Validate State</Button>
  35:     </Canvas>
  36: </Window>

 

 

从执行的结果上来看,当验证出现错误(即索引器属性返回的字符串不为空时),系统默认给出一种验证错误的显示方式(控件以红色边框包围),但是需注意两点:

    • 产生验证错误,验证后的数据仍然会更改数据源的值
    • 如果系统出现异常,如成绩值输入 “90d”,则系统不会显示错误,控件上的输入值也不赋值到数据源。这种情况下,需要使用ExceptionValidationRule。
  • ExceptionValidationRule:即当绑定目标的属性值向绑定源的属性值赋值时引发异常所产生的验证。此种方式若实现自定义的逻辑验证,通常设置数据源的属性的Set访问器,在Set访问器中,根据输入的值结合逻辑,使用throw抛出相应的异常。

例如上例中,对于Score对应的TextBox,再加入ExceptionValidationRule:

   1: <TextBox Canvas.Left="136" Canvas.Top="41" Height="23" Name="textBox2" Width="120">
   2:     <TextBox.Text>
   3:         <Binding Path="Score" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
   4:             <!--与上一个TextBox控件的写法作用相同-->
   5:             <Binding.ValidationRules>
   6:                 <DataErrorValidationRule />
   7:                 <ExceptionValidationRule />
   8:             </Binding.ValidationRules>
   9:         </Binding>
  10:     </TextBox.Text>
  11: </TextBox>

  • 自定义验证规则:定义一个类,继承ValidationRule抽象类,实现其Validate方法,验证某一输入。

例如,定义一个类,用来验证输入的Email地址是否合法(验证的Email允许为字符串的空值String.Empty,但有输入必须符合Email的格式要求)

在学生类中添加Email可读可写属性(并不做相应的验证,忽略其他重复代码):

   1: public string Email
   2: {
   3:     set; get;
   4: }

定义一个类,实现Email格式验证:

   1: using System.Globalization;
   2: using System.Text.RegularExpressions;
   3: using System.Windows.Controls;
   4:  
   5: namespace WPFDataBindingDemo
   6: {
   7:     public class EmailValidationRule : ValidationRule
   8:     {
   9:         public override ValidationResult Validate(object value, CultureInfo cultureInfo)
  10:         {
  11:             bool isValid = false;
  12:             string message = null;
  13:  
  14:             // 检查输入值不为空,且是字符串
  15:             if (value != null && value is string)
  16:             {
  17:                 string email = value.ToString();
  18:  
  19:                 // 检查输入的字符串是否为String.Empty
  20:                 if (email != string.Empty)
  21:                 {
  22:                     string emailFormartRegex =
  23:                         @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|" +
  24:                         @"(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
  25:                     
  26:                     // 检查输入的字符串是否符合Email格式
  27:                     isValid = Regex.IsMatch(email, emailFormartRegex);
  28:  
  29:                     if (! isValid)
  30:                     {
  31:                         message = "Input string not match Email Format";
  32:                     }
  33:                 }
  34:                 else
  35:                 {
  36:                     // 输入的字符串为字符串空值时,认为验证通过
  37:                     isValid = true;
  38:                 }
  39:             }
  40:             else
  41:             {
  42:                 message = "Input value is NULL or is not string.";
  43:             }
  44:  
  45:             // 返回验证结果(ValidationResult对象)
  46:             return new ValidationResult(isValid,message);
  47:         }
  48:     }
  49: }

在界面上:

   1: <TextBox Canvas.Left="104" Canvas.Top="70" Height="23" Name="textBox3" Width="152">
   2:     <Binding Mode="TwoWay" Path="Email" UpdateSourceTrigger="PropertyChanged">
   3:         <Binding.ValidationRules>
   4:             <local:EmailValidationRule />
   5:         </Binding.ValidationRules>
   6:     </Binding>
   7: </TextBox>

三、为数据验证提供视觉效果

在数据验证错误后,可以通过以下两种方式提供相应的视觉效果:

  • 定义Style及相应的触发器

如果要使输入的控件的外观发生变化,可以使用Style。例如上例中出错,使输入的文本框的背景颜色和字体颜色发生变化,并提供ToolTip显示错误信息,可以定义如下的Style:

   1: <Style TargetType="TextBox">
   2:     <Setter Property="Background" Value="White" />
   3:     <Setter Property="Foreground" Value="Black" />
   4:     <Style.Triggers>
   5:         <Trigger Property="Validation.HasError" Value="True">
   6:             <Setter Property="Background" Value="#DDD" />
   7:             <Setter Property="Foreground" Value="Red" />
   8:             <Setter Property="ToolTip"
   9:                     Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)[0].ErrorContent}"/>
  10:         </Trigger>
  11:     </Style.Triggers>
  12: </Style>

效果如下:

  • 定义控件模板

如果要为相应的控件添加一些辅助的控件,可以使用控件模板,如出现验证错误时,不使用系统默认的红色边框,而是在文本框后添加一个红色的星号:

   1: <ControlTemplate x:Key="validErrorTextBoxTemplate">
   2:     <DockPanel>
   3:         <AdornedElementPlaceholder/>
   4:         <TextBlock Foreground="Red" FontSize="20">*</TextBlock>
   5:     </DockPanel>
   6: </ControlTemplate>

并在每一个输入的TextBox中添加:

   1: Validation.ErrorTemplate="{StaticResource validErrorTextBoxTemplate}"

转载:http://www.cnblogs.com/fuchongjundream/p/3844051.html

关于WPF的验证的更多相关文章

  1. wpf数据验证实例及常用方法小结

    虽然标题是wpf数据验证,但并不是对IDataErrorInfo.ValidationRule.属性中throw Exception这几种验证方式的介绍: 之前做项目时(例如员工工资管理),根据员工编 ...

  2. WPF数据验证

    当填写表单时,需要对填写的内容进行验证,检查数据是否符合要求,比如字符串的长度.日期的格式.数字等.WPF支持自定义验证规则,并提供可视化反馈,以便在输入无效值时向用户发出通知. 下面的示例将演示一个 ...

  3. WPF MVVM 验证

    WPF MVVM(Caliburn.Micro) 数据验证 书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model ...

  4. WPF 自动验证

    WPF中TextBox的自动验证: 演示 : 用以下两个TextBox分别显示验证IP和非空值验证,先看效果: IP自动验证效果: 非空值自动验证效果: 第一步:定义TextBox验证的样式: < ...

  5. WPF数据验证方式

    WPF有两种数据验证的方式: 1 在数据对象上进行验证:普通属性验证或者实现IDataErrorInfo接口 2 可以再绑定规则上进行验证:ExceptionValidationRule异常验证规则 ...

  6. WPF TextBox 验证输入

    //验证输入为数字private void txt_time_KeyDown(object sender, KeyEventArgs e){ if (!((e.Key >= Key.D0 &am ...

  7. WPF mvvm 验证,耗时两天的解决方案

    常用类 类名 介绍 ValidationRule 所有自定义验证规则的基类.提供了让用户定义验证规则的入口. ExceptionValidation 表示一个规则,该规则检查在绑定源属性更新过程中引发 ...

  8. WPF 绑定 验证

    <TextBox Grid.Column="1" Margin="1" Text="{Binding Name, ValidatesOnExce ...

  9. WPF数据验证(4)——响应与获取验证错误

    1780 前面的示例中,有关用户接受到错误的唯一指示是在违反规则的文本框周围的红色轮廓.为了提供更多信息,可以处理 Error 事件,但存储或清除错误时会引发该事件,但前提是必须确保已将 Bindin ...

随机推荐

  1. ★10 个实用技巧,让Finder带你飞~

    10 个实用技巧,让 Finder 带你飞 Finder 是 Mac 电脑的系统程序,有的功能类似 Windows 的资源管理器.它是我们打开 Mac 首先见到的「笑脸」,有了它,我们可以组织和使用 ...

  2. [转载]python 详解re模块

    原文地址:python 详解re模块作者:Rocky 正则表达式的元字符有. ^ $ * ? { [ ] | ( ) .表示任意字符 []用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字 ...

  3. 转: 【Java并发编程】之五:volatile变量修饰符—意料之外的问题(含代码)

    转载请注明出处:     volatile用处说明     在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...

  4. 团队作业4--第一次项目冲刺(Alpha版本) 4

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 完成对查重结果的写出与保存,将查重结果写出并导出保存为Excel形式 四.困难与问题 对查重结果的保存,当有多份文档进行比较的 ...

  5. java中synchronized的使用

    synchronized是Java中的关键字,是一种同步锁. synchronized分对象锁和类的锁两种. (一)通常synchronized 方法和synchronized(this){}都是属于 ...

  6. KKlist团队目录

    KKlist团队目录 一.Daily Scrum Meeting[Alpha] 4.22 day one 4.23 day two 4.24 day three 4.25 day four 4.26 ...

  7. 201521123092《java程序设计》第五周学习总结

    1.本周学习总结 #1.1 尝试使用思维导图总结有关多态与接口的知识点. 2.书面作业 #1.代码阅读:Child压缩包内源代码##1.1 com.parent包中Child.java文件能否编译通过 ...

  8. 聊聊React高阶组件(Higher-Order Components)

    使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...

  9. mybatis-basedao的实现

    package com.yangwei.shop.dao; import java.util.HashMap; import java.util.List; import java.util.Map; ...

  10. u盘分区装机版

    第一步:制作启动U盘前的软硬件准备 .准备一个最好大于2G的U盘,并先备份好里面的数据,防止接下来需要清空U盘的数据而出现丢失重要文件: 2.下载U盘启动盘制作工具6.1软件,直接放在桌面,方便接下来 ...