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