Я в настоящее время изучаю проверку для своего приложения WPF и замеченный упоминание о IDataErrorInfo
. Однако существует немного руководств по тому, как использовать его и хуже нет ни одного, кто объясняет, как это работает.
На сайте MSND.com это дает' MSDN
public class Person : IDataErrorInfo
{
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
public string Error
{
get
{
return null;
}
}
public string this[string name]
{
get
{
string result = null;
if (name == "Age")
{
if (this.age < 0 || this.age > 150)
{
result = "Age must not be less than 0 or greater than 150.";
}
}
return result;
}
}
}
Я вижу то, что продолжается здесь, но я понятия не имею, что это действительно делает к моим данным.
Когда те 2 свойства используются? Скажем, кто-то устанавливает Age
как 400: метод set на свойстве называют. Ошибочная штука будет мешать ему быть установленной? Если не и это просто предупреждает, что число является неправильным, что должно мешать кому-то сохранить информацию, как? Существует нет IsValid()
метод для проверки, там?
Хотел бы знать то, что происходит позади занавесок.
Свойство Ошибка
обычно не используется, но вы должны определить его, чтобы реализовать интерфейс.
Как сказал дециклон, проверка не остановит установку свойства с неправильным значением, но вы можете установить для свойства значение по умолчанию.
Позвольте мне показать вам, как я его использую. У меня есть пара TextBox
, которые я должен проверить значения, которые они имеют. Вместо того, чтобы показывать MessageBox с ошибкой при вызове набора, я хочу использовать "веб-подход": я хочу, чтобы граница и фон TextBox
были красными при установке недопустимого значения и всплывающая подсказка TextBox
, чтобы показать полученную ошибку.
Это мой xaml для TextBox:
<converters:ValidationConverter x:Key="validationConverter"/>
<Style x:Key="TestStepTextBox" TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource validationConverter}, 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="{Binding RunAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource TestStepTextBox}"/>
<TextBox Name="txtStopAfter" Text="{Binding StopAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource TestStepTextBox}"/>
очень важное замечание о конвертере. У меня возникло исключение, когда я ввел недопустимое значение, а затем установил хорошее значение. Каким-то образом, возможно, связано с наличием UpdateSourceTrigger = PropertyChanged
, было время, когда свойство HasError было истинным, но не было установлено ошибок (см. ссылка ). Итак, вот код для конвертера:
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(); //sets the property value to the model layer
}
}
}
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;
}
Что я знаю о IDataErrorInfo
, так это то, что он используется только для UI
целей. Он обеспечивает простой способ привязки сообщения об ошибке к WPF UI
. Поскольку WPF UI
"идентифицирует" объекты, реализующие IDataErrorInfo
так же, как INotifyPropertyChanged
, вам не придется писать дополнительный код для отображения сообщений об ошибках в UI
.
И еще одно, это не помешает установить неправильное значение. Он просто сообщит WPF UI
(когда WPF UI
вызывает индексатор, передающий имя свойства), что значение в конкретном свойстве недопустимо.