IsChanged = true;
}
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(string.Empty));
}
Теперь при выполнении того же самого теста текстовые поля Make и Color декорируются с помощью шаблона отображения ошибки, когда одно из них обновляется. Так почему бы ни генерировать событие всегда в такой манере? В значительной степени причиной является производительность. Вполне
Другое решение предполагает генерацию события PropertyChanged для зависимого поля (полей), когда одно из полей изменяется. Недостаток такого приема в том, что вы (или другие разработчики, сопровождающие ваше приложение) должны знать о взаимосвязи между свойствами Make и Color через код проверки достоверности.
Интерфейс INotifyDataErrorInfo
Интерфейс INotifyDataErrorInfo, появившийся в версии .NET 4.5, построен на основе интерфейса IDataErrorInfo и предлагает дополнительные возможности для проверки достоверности. Конечно, возросшая мощь сопровождается дополнительной работой! По разительному контрасту с предшествующими приемами проверки достоверности, которые вы видели до сих пор, свойство привязки ValidatesOnNotifyDataErrors имеет стандартное значение true, поэтому добавлять его к операторам привязки не обязательно.
Интерфейс INotifyDataErrorInfo чрезвычайно мал, но, как вскоре будет показано, для обеспечения своей эффективности требует написания порядочного объема связующего кода. Ниже приведено определение интерфейса INotifyDataErrorInfo:
public interface INotifyDataErrorInfo
{
bool HasErrors { get; }
event EventHandler
ErrorsChanged;
IEnumerable GetErrors(string propertyName);
}
Свойство HasErrors используется механизмом привязки для выяснения, есть ли GetErrors() вызывается со значением null или пустой строкой в параметре propertyName, то он возвращает все ошибки, существующие в экземпляре. Если методу передан параметр propertyName, тогда возвращаются только ошибки, относящиеся к конкретному свойству. Событие ErrorsChanged (подобно событиям PropertyChanged и CollectionChanged) уведомляет механизм привязки о необходимости обновления пользовательского интерфейса для текущего списка ошибок.
Реализация поддерживающего кода
При реализации INotifyDataErrorInfo большая часть кода обычно помещается в базовый класс модели, поэтому она пишется только один раз. Начните с замены IDataErrorInfo интерфейсом INotifyDataErrorInfo в файле класса CarPartial.cs (код для IDataErrorInfo в классе можете оставить; вы обновите его позже).
public partial class Car: INotifyDataErrorInfo, IDataErrorInfo
{
...
public IEnumerable GetErrors(string propertyName)
{
throw new NotImplementedException();
}
public bool HasErrors { get; }
public event
EventHandler
}
Добавьте закрытое поле типа Dictionary, которое будет хранить сведения о любых ошибках, сгруппированные по именам свойств. Понадобится также добавить оператор using для пространства имен System.Collections.Generic. Вот как выглядит код:
using System.Collections.Generic;
private readonly Dictionary
= new Dictionary
Свойство HasErrors должно возвращать true, если в словаре присутствуют
public bool HasErrors => _errors.Any();
Создайте вспомогательный метод для инициирования события ErrorsChanged (подобно инициированию события PropertyChanged):
private void OnErrorsChanged(string propertyName)
{
ErrorsChanged?.Invoke(this,
new DataErrorsChangedEventArgs(propertyName));
}