После внесения изменений в конструкции привязки индексатор вызывается на модели каждый раз, когда возникает событие PropertyChanged
. В качестве параметра columnName
индексатора используется имя свойства из события. Если индексатор возвращает string.Empty
, то инфраструктура предполагает, что все проверки достоверности прошли успешно и какие-либо ошибки отсутствуют. Если индексатор возвращает значение, отличающееся от string.Empty
, тогда в свойстве для данного объекта присутствует ошибка, из-за чего каждый элемент управления, привязанный к этому свойству специфического экземпляра класса, считается содержащим ошибку. Свойство HasError
объекта Validation
устанавливается в true
и активизируется декоратор ErrorTemplate
для элементов управления, на которые повлияла ошибка.
Добавьте простую логику проверки достоверности к индексатору в файле CorePartial.cs
. Правила проверки элементарны :
• если Make
равно ModelT
, то установить сообщение об ошибке в "Too Old"
(слишком старая модель);
• если Make
равно Chevy
и Color
равно Pink
, то установить сообщение об ошибке в $" {Make}'s don't come in {Color}"
(модель в таком цвете не поставляется).
Начните с добавления оператора switch
для каждого свойства. Во избежание применения "магических" строк в операторах case
вы снова будете использовать операцию nameof
. В случае сквозного прохода через оператор switch
возвращается string.Empty
. Далее добавьте правила проверки достоверности. В подходящих операторах case
реализуйте проверку значения свойства на основе приведенных выше правил. В операторе case
для свойства Make
первым делом проверьте, равно ли значение ModelT
. Если это так, тогда возвратите сообщение об ошибке. В случае успешного прохождения проверки в следующей строке кода вызовите вспомогательный метод, который возвратит сообщение об ошибке, если нарушено второе правило, или string.Empty
, если нет. В операторе case
для свойства Color
просто вызовите тот же вспомогательный метод. Ниже показан код:
public string this[string columnName]
{
get
{
switch (columnName)
{
case nameof(Id):
break;
case nameof(Make):
return Make == "ModelT"
? "Too Old"
: CheckMakeAndColor();
case nameof(Color):
return CheckMakeAndColor();
case nameof(PetName):
break;
}
return string.Empty;
}
}
internal string CheckMakeAndColor()
{
if (Make == "Chevy" && Color == "Pink")
{
return $"{Make}'s don't come in {Color}";
}
return string.Empty;
}
Запустите приложение, выберите автомобиль Red Rider
(Ford
) и измените значение в поле Make (Производитель) на ModelT
. После того, как фокус покинет поле, появится декоратор ошибки красного цвета. Выберите в поле со списком автомобиль Kit
(Chevy
) и щелкните на кнопке Change Color, чтобы изменить его цвет на Pink
. Вокруг поля Color
незамедлительно появится декоратор ошибки красного цвета, но возле поля Make он будет отсутствовать. Измените значение в поле Make на Ford
и переместите фокус из этого поля; декоратор ошибки красного цвета не появляется!
Причина в том, что индексатор выполняется, только когда для свойства сгенерировано событие PropertyChanged
. Как обсуждалось в разделе "Система уведомлений привязки WPF" ранее в главе, событие PropertyChanged
инициируется при изменении исходного значения свойства объекта, что происходит либо через код (вроде обработчика события Click
для кнопки Change Color), либо через взаимодействие с пользователем (синхронизируется с помощью UpdateSourceTrigger
). При изменении цвета свойство Make не изменяется, а потому событие PropertyChanged
для него не генерируется. Поскольку событие не генерируется, индексатор не вызывается и проверка достоверности для свойства Make
не выполняется.
Решить проблему можно двумя путями. Первый предусматривает изменение объекта PropertyChangedEventArgs
, которое обеспечит обновление всех привязанных свойств, за счет передачи его конструктору значения string.Empty
вместо имени поля. Как упоминалось ранее, это заставит механизм привязки обновить OnPropertyChanged()
со следующим кодом:
protected virtual void OnPropertyChanged([CallerMemberName]
string propertyName = "")
{
if (propertyName != nameof(IsChanged))
{