Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
На заметку! В каждом разделе главы можно продолжить работу с проектом из предыдущего раздела или создать копию проекта, специально предназначенную для нового раздела. Всем последующим разделам соответствуют отдельные проекты, которые доступны в каталоге с кодом для настоящей главы внутри хранилища GitHub.
Модификация примера для демонстрации проверки достоверности
В каталоге для этой главы внутри хранилища GitHub новый проект (скопированный из предыдущего примера) называется WpfValidations. Если вы работаете с тем же самым проектом, созданным в предыдущем разделе, то при копировании в свой проект кода из примеров, приведенных в текущем разделе, просто должны обращать внимание на изменения пространств имен.
Класс Validation
Прежде чем добавлять проверку достоверности в проект, важно понять назначение класса Validation. Он входит в состав инфраструктуры проверки достоверности и предоставляет методы и присоединяемые свойства, которые могут применяться для отображения результатов проверки. При обработке ошибок проверки обычно используются три основных свойства класса Validation, кратко описанные в табл. 28.2. Они будут применяться далее в разделе.
Варианты проверки достоверности
Как упоминалось ранее, технологии XAML поддерживают несколько механизмов для встраивания логики проверки достоверности внутрь приложения. В последующих разделах рассматриваются три самых распространенных варианта проверки.
Уведомление по исключениям
Хотя исключения не должны использоваться для обеспечения выполнения бизнес-логики, они могут (и будут) возникать, а потому требуют надлежащей обработки. Если исключения не обработаны в коде, тогда пользователь должен получить визуальную обратную связь об имеющейся проблеме. В отличие от Windows Forms в инфраструктуре WPF исключения привязки (по умолчанию) не распространяются до пользователя как собственно исключения. Тем не менее, они указываются визуально с применением декоратора (визуального уровня, который находится над элементами управления).
Запустите приложение, выберите запись в элементе ComboВох и очистите значение в текстовом поле Id. Поскольку свойство Id определено как имеющее тип int (не тип int, допускающий null), требуется числовое значение. После покидания поля Id по нажатию клавиши <ТаЬ> механизм привязки отправляет свойству CarId пустую строку, но из-за того, что пустая строка не может быть преобразована в значение int, внутри блока set генерируется исключение. В нормальных обстоятельствах необработанное исключение привело бы к отображению окна сообщения пользователю, но в данном случае ничего подобного не происходит. Взглянув на порцию Debug (Отладка) окна Output (Вывод), вы заметите следующие строки:
System.Windows.Data Error: 7 : ConvertBack cannot convert value '' (type 'String').
BindingExpression:Path=Id; DataItem='Car' (HashCode=52579650); target element is
'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.
FormatException: Input string was not in a correct format.
Ошибка System.Windows.Data: 7 : ConvertBack не может преобразовать (типа String).
BindingExpression : Path=Id; DataItem='Car' (HashCode=52579650);
целевой элемент - TextBox (Name=''); целевое свойство - Text
(типа String) FormatExceptionSystem.FormatException:
Входная строка не имела корректный формат.
Визуально исключение представляется с помощью тонкого прямоугольника красного цвета вокруг элемента управления (рис. 28.2).
Прямоугольник красного цвета — это свойство ErrorTemplate объекта Validation, которое действует в качестве декоратора для связанного элемента управления. Несмотря на то что стандартный внешний вид говорит о наличии ошибки, нет никакого указания на то, что именно пошло не так. Хорошая новость в том, что шаблон отображения ошибки в свойстве ErrorTemplate является полностью настраиваемым, как вы увидите позже в главе.
Интерфейс IDataErrorInfo
Интерфейс IDataErrorInfo предоставляет механизм для добавления специальной проверки достоверности в классы моделей. Данный интерфейс добавляется прямо в классы моделей (или моделей представлений), а код проверки помещается внутрь классов моделей (предпочтительно в частичные классы). Такой подход централизует код проверки достоверности в проекте, что совершенно не похоже на инфраструктуру Windows Forms, где проверка обычно делалась в самом пользовательском интерфейсе.
Показанный далее интерфейс IDataErrorInfo содержит два свойства: индексатор и строковое свойство по имени Error. Следует отметить, что механизм привязки WPF не задействует свойство Error.
public interface IDataErrorInfo
{
string this[string columnName] { get; }
string Error { get; }
}
Вскоре вы добавите частичный класс Car, но сначала необходимо модифицировать класс в файле Car.cs, пометив его как частичный. Добавьте в папку Models еще один файл по имени CarPartial.cs. Переименуйте этот класс в Car, пометьте его как partial и обеспечьте реализацию классом интерфейса IDataErrorInfo. Затем реализуйте члены интерфейса IDataErrorInfo. Вот начальный код:
public partial class Car : IDataErrorInfo
{
public string this[string columnName] => string.Empty;
public string Error { get;}
}
Чтобы привязанный элемент управления мог работать с интерфейсом IDataErrorInfo, в выражение привязки потребуется добавить ValidatesOnDataErrors. Модифицируйте выражение привязки для текстового поля Make следующим образом (и аналогично обновите остальные конструкции привязки):
<TextBox Grid.Column="1" Grid.Row="1"
Text="{Binding Path=Make, ValidatesOnDataErrors=True}" />
После внесения изменений в конструкции привязки индексатор вызывается на модели каждый раз, когда возникает событие 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 вы снова будете использовать операцию