.Age);
<Grid DataContext="{Binding PersonValidateInSetter}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Name:" />
<TextBox Grid.Column="1"
Margin="1"
Text="{Binding Name,
ValidatesOnExceptions=True,
UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1" Text="Age:" />
<TextBox Grid.Row="1"
Grid.Column="1"
Margin="1"
Text="{Binding Age,
ValidatesOnExceptions=True,
UpdateSourceTrigger=PropertyChanged}" />
</Grid>
当输入的值,在setter方法中校验时出现错误,就会出现一个红色的错误框。
关键代码:ValidatesOnExceptions=True, UpdateSourceTrigger=PropertyChanged。
PS:这种方式有一个BUG,首次加载时不会对默认数据进行检验。
2、继承IDataErrorInfo接口
使Model对象继承IDataErrorInfo接口,并实现一个索引进行校验。如果索引返回空表示没有错误,如果返回不为空,
表示有错误。另外一个Erro属性,但是在WPF中没有被用到。
public class PersonDerivedFromIDataErrorInfo : ObservableObject, IDataErrorInfo
private string name;
private int age;
public string Name
return this.name;
this.name = value;
this.OnPropertyChanged(() => this.Name);
public int Age
return this.age;
this.age = value;
this.OnPropertyChanged(() => this.Age);
// never called by WPF
public string Error
return null;
public string this[string propertyName]
switch (propertyName)
case "Name":
if (string.IsNullOrWhiteSpace(this.Name))
return "Name cannot be empty!";
if (this.Name.Length < 4)
return "Name must have more than 4 char!";
break;
case "Age":
if (this.Age < 18)
return "You must be an adult!";
break;
return null;
<Grid DataContext="{Binding PersonDerivedFromIDataErrorInfo}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Name:" />
<TextBox Grid.Column="1"
Margin="1"
Text="{Binding Name,
NotifyOnValidationError=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1" Text="Age:" />
<TextBox Grid.Row="1"
Grid.Column="1"
Margin="1"
Text="{Binding Age,
NotifyOnValidationError=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}" />
PS:这种方式,没有了第一种方法的BUG,但是相对很麻烦,既需要继承接口,又需要添加一个索引,如果遗留代码,那么这种方式就不太好。
3、自定义校验规则
一个数据对象或许不能包含一个应用要求的所有不同验证规则,但是通过自定义验证规则就可以解决这个问题。
在需要的地方,添加我们创建的规则,并进行检测。
通过继承ValidationRule抽象类,并实现Validate方法,并添加到绑定元素的Binding.ValidationRules中。
public class MinAgeValidation : ValidationRule
public int MinAge { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
ValidationResult result = null;
if (value != null)
int age;
if (int.TryParse(value.ToString(), out age))
if (age < this.MinAge)
result = new ValidationResult(false, "Age must large than " + this.MinAge.ToString(CultureInfo.InvariantCulture));
result = new ValidationResult(false, "Age must be a number!");
result = new ValidationResult(false, "Age must not be null!");
return new ValidationResult(true, null);
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Name:" />
<TextBox Grid.Column="1" Margin="1" Text="{Binding Name}">
</TextBox>
<TextBlock Grid.Row="1" Text="Age:" />
<TextBox Grid.Row="1"
Grid.Column="1"
Margin="1">
<TextBox.Text>
<Binding Path="Age"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<validations:MinAgeValidation MinAge="18" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
这种方式,也会有第一种方法的BUG,暂时还不知道如何解决,但是这个能够灵活的实现校验,并且能传参数。
4、使用数据注解(特性方式)
在System.ComponentModel.DataAnnotaions命名空间中定义了很多特性,
它们可以被放置在属性前面,显示验证的具体需要。放置了这些特性之后,
属性中的Setter方法就可以使用Validator静态类了,来用于验证数据。
public class PersonUseDataAnnotation : ObservableObject
private int age;
private string name;
[Range(18, 120, ErrorMessage = "Age must be a positive integer")]
public int Age
return this.age;
this.ValidateProperty(value, "Age");
this.SetProperty(ref this.age, value, () => this.Age);
[Required(ErrorMessage = "A name is required")]
[StringLength(100, MinimumLength = 3, ErrorMessage = "Name must have at least 3 characters")]
public string Name
return this.name;
this.ValidateProperty(value, "Name");
this.SetProperty(ref this.name, value, () => this.Name);
protected void ValidateProperty<T>(T value, string propertyName)
Validator.ValidateProperty(value,
new ValidationContext(this, null, null) { MemberName = propertyName });
}
}
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Name:" />
<TextBox Grid.Column="1"
Margin="1"
Text="{Binding Name,
ValidatesOnExceptions=True,
UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1" Text="Age:" />
<TextBox Grid.Row="1"
Grid.Column="1"
Margin="1"
Text="{Binding Age,
ValidatesOnExceptions=True,
UpdateSourceTrigger=PropertyChanged}" />
</Grid>
使用特性的方式,能够很自由的使用自定义的规则,而且在.Net4.5中新增了很多特性,可以很方便的对数据进行校验。
例如:EmailAddress, Phone, and Url等。
三、自定义错误显示模板
在上面的例子中,我们可以看到当出现验证不正确时,绑定控件会被一圈红色错误线包裹住。
这种方式一般不能够正确的展示出,错误的原因等信息,所以有可能需要自己的错误显示方式。
前面,我们已经讲过了。当在检测过程中,出现错误时,WPF会把错误信息封装为一个ValidationError对象,
并添加到Validation.Errors中,所以我们可以取出错误详细信息,并显示出来。
1、为控件创建ErrorTemplate
下面就是一个简单的例子,每次都把错误信息以红色展示在空间上面。这里的AdornedElementPlaceholder相当于
控件的占位符,表示控件的真实位置。这个例子是在书上直接拿过来的,只能做基本展示用。
<ControlTemplate x:Key="ErrorTemplate">
<Border BorderBrush="Red" BorderThickness="2">
<AdornedElementPlaceholder x:Name="_el" />
<TextBlock Margin="0,0,6,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Foreground="Red"
Text="{Binding [0].ErrorContent}" />
</Grid>
</Border>
</ControlTemplate>
<TextBox x:Name="AgeTextBox"
Grid.Row="1"
Grid.Column="1"
Margin="1" Validation.ErrorTemplate="{StaticResource ErrorTemplate}" >
使用方式非常简单,将上面的模板作为逻辑资源加入项目中,然后像上面一样引用即可。
对知识梳理总结,希望对大家有帮助!
作者:ColdJokeLife
出处:http://www.cnblogs.com/ColdJokeLife/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,请联系我,非常感谢。