Error
属性通常不被使用,但是你必须定义它才能实现接口。
正如decyclone所说,验证无法阻止使用错误值设置属性,但你可以将属性设置为默认值。
让我向你展示我的用法。我有几个
TextBox
需要验证它们的值。当调用set时,我不想显示一个带有错误信息的MessageBox,我想采取一种“网页”方法:当设置无效值时,我希望
TextBox
的边框和背景变为红色,并且
TextBox
的工具提示显示其收到的错误信息。
这是我为TextBox编写的XAML:
<converters:ValidationConverter x:Key="validationConverter"/>
<Style x:Key="TestStepTextBox" TargetType="">
<Setter Property="Validation.ErrorTemplate" Value=""/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="">
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="" BorderBrush="" BorderThickness="">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels=""/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value=",
Converter=, Path=(Validation.Errors)}"/>
<Setter Property="Background" Value="#33FF342D"/>
<Setter Property="BorderBrush" Value="#AAFF342D"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<TextBox Name="txtRunAfter" Text="" Style=""/>
<TextBox Name="txtStopAfter" Text="" Style=""/>
关于转换器的一个非常重要的注意事项。当我输入无效值并设置好值后,我遇到了异常。不知道是否与UpdateSourceTrigger=PropertyChanged
有关,在某些情况下,HasError属性为true但没有设置错误(见链接)。因此,这是转换器的代码:
public class ValidationConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ReadOnlyObservableCollection<ValidationError> errors = value as ReadOnlyObservableCollection<ValidationError>;
if (errors == null) return value;
if (errors.Count > 0)
{
return errors[0].ErrorContent;
}
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException("This method should never be called");
}
}
为了防止无效值保存到我的模型层,我使用相同的方法来检查是否应该提交数据到模型。如果该值无效,我只设置属性并不调用模型中属性的设置。请查看以下代码:
private int _runAfter = 0;
public int RunAfter
{
get
{
return _runAfter;
}
set
{
if (_runAfter != value)
{
_runAfter = value;
OnPropertyChanged("RunAfter");
if (validateRunAfter() == null)
setRunAfter();
}
}
}
string IDataErrorInfo.this[string columnName]
{
get
{
string message = null;
if (columnName == "RunAfter")
message = validateRunAfter();
return message;
}
}
private string validateRunAfter()
{
if (value >= _order)
return "Run After value must be less than its Step Order (#) value.";
return null;
}