Еще одним преимуществом наблюдаемых моделей является способность отслеживать изменения состояния. Отслеживать флаги изменения (т.е. когда изменяется одно и более значений объекта) в WPF довольно легко. Добавьте в класс Car
свойство типа bool
по имени IsChanged
. Внутри его блока set
вызовите метод OnPropertyChanged()
, как поступали с другими свойствами класса Car
.
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
:
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
, который отвечает за ввод цвета: