c# – 如何在使用自定义ValidationAttribute和INotifyDataErrorInfo验证另一个属性时触发对一个属性的验证
作者:互联网
直到最近,我使用了IDataErrorInfo接口的自定义扩展版本.我的扩展程序使我能够同时处理多个错误,到目前为止,它对我很有帮助.然而,随着INotifyDataErrorInfo接口的引入,我想我会试验它,看看是否有任何改进.
在阅读了一些在线教程之后,我使用了System.ComponentModel.DataAnnotations命名空间中的各种ValidationAttributes.使用这些属性可以提供如下基本验证规则:
[MinLength(3, ErrorMessage = "Name must be longer than 3 characters.")]
public string Name
{
get { return name; }
set { name = value; NotifyPropertyChanged("Name"); Validate("Name", name); }
}
最初,它似乎非常好,因为错误消息插入到应用的ErrorTemplates中可用的Valaidation.Errors集合中.但是,大多数内置验证规则都是基本的,我习惯于必须实现涉及其他属性值的复杂验证规则.
所以我开始寻找一种方法来创建一个涉及多个属性的简单验证规则:必须设置两个或多个字段之一的规则.所以我声明了一个扩展ValidationAttribute的类,在网上搜索后,找到了一种访问其他属性值的方法.
我使用应用于每个TextBox的自定义ErrorTemplate打开了一个基本UI,它显示了数据绑定属性的Validation.Errors集合:
<ControlTemplate x:Key="ErrorTemplate">
<StackPanel Orientation="Horizontal">
<Border BorderBrush="#4FFF0000" BorderThickness="1" Margin="0,10">
<AdornedElementPlaceholder />
</Border>
<Image Name="WarningImage" Source="pack://application:,,,/WpfApplication1;component/Images/Warning_16.png" Margin="5,0,0,0" Tag="{Binding}" />
<Popup PlacementTarget="{Binding ElementName=WarningImage}" Placement="Right" Margin="5,0,0,0" AllowsTransparency="True" IsOpen="True">
<Border BorderThickness="1" BorderBrush="#4FFF0000" CornerRadius="5" Background="White" Padding="5" Margin="10">
<Border.Effect>
<DropShadowEffect Color="Red" Opacity="0.5" BlurRadius="15" ShadowDepth="0" />
</Border.Effect>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</Popup>
</StackPanel>
</ControlTemplate>
在Name属性上设置了我的自定义属性,我设法在没有设置属性的情况下通过接口将ValidationResult添加到Validation.Errors集合中,但问题是:如果我将一个值添加到其他一个绑定到的TextBoxes数据中其他必需的属性,第一个TextBox中的错误消息将保留在那里.
如果我回到第一个TextBox并输入了一些东西,那么验证就可以了,所以即使我删除了它,它仍然知道设置了一个必需的属性.因此验证代码可以正常工作,但问题是属性更改为其他必需属性不会触发Name属性中的验证.
即使我将相同的自定义属性应用于其他必需的属性,同样的事情也发生了……每个验证错误只有在键入其相关的TextBox时才会清除.我还尝试了内置的CustomValidationAttribute,它允许我们调用类中的方法来验证,但最终结果是相同的.
验证代码有效,但不会从其他必需的属性更改中触发.我甚至尝试调用Validate方法,传入其他属性的名称,但以连续循环结束.所以问题是,当另一个属性被验证时,如何在一个属性上触发验证?
解决方法:
这是我在包含From和To属性的类中所做的.我想验证From小于或等于To.
使用CustomValidationAttribute应用验证逻辑,这比创建自己的验证属性类更容易.您只需告诉它类的类型,以及要包含验证逻辑的方法的名称(该方法必须具有特定的签名).这是我的相关代码: –
[CustomValidation(typeof(MyModel), "ValidateRange")]
public double From
{
get
{
return _from;
}
set
{
if (_from != value)
{
_from = value;
OnPropertyChanged("From");
// Validate the other side
ValidateProperty("To", _to);
}
}
}
[CustomValidation(typeof(MyModel), "ValidateRange")]
public double To
{
get
{
return _to;
}
set
{
if (_to != value)
{
_to = value;
OnPropertyChanged("To");
// Validate the other side
ValidateProperty("From", _from);
}
}
}
private static ValidationResult ValidateRange(ValidationContext validationContext)
{
var model = validationContext.ObjectInstance as MyModel;
if (model.From > model.To)
{
return new ValidationResult("Invalid range");
}
return null;
}
如您所见,一个属性setter中的代码强制验证“other”属性,正如您在上一段中提到的那样.没有理由为什么它应该进入无限循环,除非你的验证代码试图设置其中一个属性,这将触发另一个调用Validate(),依此类推,等等.
标签:c,wpf,validation,validationattribute,inotifydataerrorinfo 来源: https://codeday.me/bug/20190703/1363824.html