Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

private bool _isChanged;

public bool IsChanged {

get => _isChanged;

set

{

if (value == _isChanged) return;

_isChanged = value;

OnPropertyChanged;

}

}

Свойство

IsChanged
необходимо устанавливать в
true
внутри метода
OnPropertyChanged
. Важно не устанавливать свойство
IsChanged
в
true
в случае изменения его самого, иначе сгенерируется исключение
переполнения стека! Модифицируйте метод
OnPropertyChanged
следующим образом (здесь используется описанная ранее операция
nameof
):

protected virtual void OnPropertyChanged(

[CallerMemberName] string propertyName = "")

{

if (propertyName != nameof(IsChanged))

{

IsChanged = true;

}

PropertyChanged?.Invoke(this,

new PropertyChangedEventArgs(propertyName));

}

Откройте файл

MainWindow.xaml
и добавьте в
DetailsGrid
дополнительный элемент
RowDefinition
. Поместите в конец элемента
Grid
показанную ниже разметку, которая содержит элементы управления
Label
и
Checkbox
, привязанные к свойству
IsChanged
:

<Label Grid.Column="0" Grid.Row="5" Content="Is Changed"/>

<CheckBox Grid.Column="1" Grid.Row="5" VerticalAlignment="Center"

Margin="10,0,0,0" IsEnabled="False" IsChecked="{Binding Path=IsChanged}" />

Если вы запустите приложение прямо сейчас, то увидите, что каждая отдельная запись отображается как измененная, хотя пока ничего не изменялось! Дело в том, что во время создания объекта устанавливаются значения свойств, а установка любых значений приводит к вызову метода

OnPropertyChanged
, который и устанавливает свойство
IsChanged
объекта. Чтобы устранить проблему, установите свойство
IsChanged
в
false
последним в коде инициализации объекта. Откройте файл
MainWindow.xaml.cs
и модифицируйте код создания списка:

_cars.Add(

new Car {Id = 1, Color = "Blue", Make = "Chevy",

PetName = "Kit", IsChanged = false});

_cars.Add(

new Car {Id = 2, Color = "Red", Make = "Ford",

PetName = "Red Rider", IsChanged =
false});

Снова запустите приложение, выберите автомобиль и щелкните на кнопке Change Color. Флажок Is Changed (Изменено) становится отмеченным наряду с изменением цвета.

Обновление источника через взаимодействие с пользовательским интерфейсом

Во время выполнения приложения можно заметить, что при вводе в текстовых полях флажок Is Changed не становится отмеченным до тех пор, пока фокус не покинет элемент управления, где производился ввод. Причина кроется в свойстве

UpdateSourceTrigger
привязок элементов
TextBox
.

Свойство

UpdateSourceTrigger
определяет, какое событие (изменение значения, переход фокуса и т.д.) является основанием для обновления пользовательским интерфейсом лежащих в основе данных. Перечисление
UpdateSourceTrigger
принимает значения, описанные в табл. 28.1.

Стандартным событием обновления для элементов управления

TextBox
является
LostFocus
. Измените его на
PropertyChanged
, модифицировав привязку для элемента
TextBox
, который отвечает за ввод
цвета:

<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Path=Color,

UpdateSourceTrigger=PropertyChanged}" />

Если вы запустите приложение и начнете ввод в текстовом поле Color (Цвет), то флажок Is Changed немедленно отметится. Может возникнуть вопрос о том, почему для элементов управления

TextBox
в качестве стандартного выбрано значение
LostFocus
. Дело в том, что проверка достоверности (рассматриваемая вскоре) для модели запускается в сочетании с
UpdateSourceTrigger
. В случае
TextBox
это может потенциально вызывать ошибки, которые будут постоянно возникать до тех пор, пока пользователь не введет корректное значение. Например, если правила проверки достоверности не разрешают вводить в элементе
TextBox
менее пяти символов, тогда сообщение об ошибке будет отображаться при каждом нажатии клавиши, пока пользователь не введет пять или более символов. В таких случаях с обновлением источника лучше подождать до момента, когда пользователь переместит фокус из элемента
TextBox
(завершив изменение текста).

Итоговые сведения об уведомлениях и наблюдаемых моделях

Применение интерфейсов

INotifyPropertyChanged
в моделях и классов
ObservableCollection
для списков улучшает пользовательский интерфейс приложения за счет поддержания его в синхронизированном состоянии с данными. В то время как ни один из интерфейсов не является сложным, они требуют обновлений кода. К счастью, в инфраструктуре предусмотрен класс
ObservableCollection
, поддерживающий все необходимое для создания наблюдаемых коллекций. Также удачей следует считать обновление проекта Fody с целью автоматического добавления функциональности
INotifyPropertyChanged
. При наличии под рукой упомянутых двух инструментов нет никаких причин отказываться от реализации наблюдаемых моделей в своих приложениях WPF.

Проверка достоверности WPF

Теперь, когда интерфейс

INotifyPropertyChanged
реализован и задействован класс
ObservableCollection
, самое время заняться добавлением в приложение средств проверки достоверности. Приложениям необходимо проверять пользовательский ввод и обеспечивать обратную связь с пользователем, если введенные им данные оказываются некорректными. В настоящем разделе будут раскрыты наиболее распространенные механизмы проверки достоверности для современных приложений WPF, но это лишь часть возможностей, встроенных в инфраструктуру WPF.

Проверка достоверности происходит, когда привязка данных пытается обновить источник данных. В дополнение к встроенным проверкам, таким как исключения в блоках

set
для свойств, можно создавать специальные правила проверки достоверности. Если любое правило проверки достоверности (встроенное или специальное) нарушается, то в игру вступает класс
Validation
, который обсуждается позже в главе.

На заметку! В каждом разделе главы можно продолжить работу с проектом из предыдущего раздела или создать копию проекта, специально предназначенную для нового раздела. Всем последующим разделам соответствуют отдельные проекты, которые доступны в каталоге с кодом для настоящей главы внутри хранилища GitHub.

Модификация примера для демонстрации проверки достоверности

В каталоге для этой главы внутри хранилища GitHub новый проект (скопированный из предыдущего примера) называется

WpfValidations
. Если вы работаете с тем же самым проектом, созданным в предыдущем разделе, то при копировании в свой проект кода из примеров, приведенных в текущем разделе, просто должны обращать внимание на изменения пространств имен.

Класс Validation

Прежде чем добавлять проверку достоверности в проект, важно понять назначение класса

Validation
. Он входит в состав инфраструктуры проверки достоверности и предоставляет методы и присоединяемые свойства, которые могут применяться для отображения результатов проверки. При обработке ошибок проверки обычно используются три основных свойства класса
Validation
, кратко описанные в табл. 28.2. Они будут применяться далее в разделе.

Поделиться с друзьями: