Возникает вопрос: когда приведенный выше код активизируется? Механизм привязки прослушивает событие ErrorsChanged
и обновляет пользовательский интерфейс, если в коллекции ошибок для выражения привязки возникает изменение. Но код проверки по-прежнему нуждается в триггере для запуска. Доступны два механизма, которые обсуждаются далее.
Использование интерфейса INotifyDataErrorInfo для проверки достоверности
Одним из мест выполнения проверки на предмет ошибок являются блоки set
для свойств, как демонстрируется в показанном ниже примере, упрощенном до единственной проверки на равенство свойства Make
значению ModelT
:
public string Make
{
get { return _make; }
set
{
if (value == _make) return;
_make = value;
if (Make == "ModelT")
{
AddError(nameof(Make), "Too Old");
}
else
{
ClearErrors(nameof(Make));
}
OnPropertyChanged(nameof(Make));
OnPropertyChanged(nameof(Color));
}
}
Основная проблема такого подхода состоит в том, что вам приходится сочетать логику проверки достоверности с блоками set
для свойств, что делает код труднее в чтении и сопровождении.
Комбинирование IDataErrorInfo С INotifyDataErrorInfo для проверки достоверности
В предыдущем разделе было показано, что реализацию интерфейса IDataErrorInfo
можно добавить к частичному классу, т.е. обновлять блоки set
не понадобится. Кроме того, индексатор автоматически вызывается при возникновении события PropertyChanged
в свойстве. Комбинирование IDataErrorInfo
и INotifyDataErrorInfo
предоставляет дополнительные возможности для проверки достоверности из INotifyDataErrorInfo
, а также отделение от блоков set
, обеспечиваемое IDataErrorInfo
.
Цель применения IDataErrorInfo
не в том, чтобы запускать проверку достоверности, а в том, чтобы гарантировать вызов кода проверки, который задействует INotifyDataErrorInfo
, каждый раз, когда для объекта генерируется событие PropertyChanged
. Поскольку интерфейс IDataErrorInfo
не используется для проверки достоверности, необходимо всегда возвращать string.Empty
из индексатора. Модифицируйте индексатор и вспомогательный метод CheckMakeAndColor
следующим образом:
public string this[string columnName]
{
get
{
ClearErrors(columnName);
switch (columnName)
{
case nameof(Id):
break;
case nameof(Make):
CheckMakeAndColor;
if (Make == "ModelT")
{
AddError(nameof(Make), "Too Old");
hasError = true;
}
break;
case nameof(Color):
CheckMakeAndColor;
break;
case nameof(PetName):
break;
}
return string.Empty;
}
}
internal bool CheckMakeAndColor
{
if (Make == "Chevy" && Color == "Pink")
{
AddError(nameof(Make), $"{Make}'s don't come in {Color}");
AddError(nameof(Color),
$"{Make}'s don't come in {Color}");
return true;
}
return false;
}
Запустите приложение, выберите автомобиль Chevy
и измените цвет на Pink
. В дополнение к декораторам красного цвета вокруг текстовых полей Make и Model будет также отображаться декоратор в виде красного прямоугольника, охватывающего целиком всю сетку, в которой находятся поля с детальной информацией об автомобиле (рис. 28.3).
Это еще одно преимущество применения интерфейса INotifyDataErrorInfo
. В дополнение к элементам управления, которые содержат ошибки, элемент управления, определяющий контекст данных, также декорируется шаблоном отображения ошибки.
Отображение всех ошибок
Свойство Errors
класса Validation
возвращает все ошибки проверки достоверности для конкретного объекта в форме объектов ValidationError
. Каждый объект ValidationError
имеет свойство ErrorContent
, которое содержит список сообщений об ошибках для свойства. Это означает, что сообщения об ошибках, которые нужно отобразить, находятся в списке внутри списка. Чтобы вывести их надлежащим образом, понадобится создать элемент ListBox
, содержащий еще один элемент ListBox
. Звучит слегка запутанно, но вскоре все прояснится.
Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT