private void BtnChangeColor_OnClick(object sender, RoutedEventArgs e)

{

  _cars.First(x => x.Id == ((Car)cboCars.SelectedItem)?.Id).Color = "Pink";

}

Запустите приложение, выберите автомобиль и щелкните на кнопке Change Color (Изменить цвет). Никаких видимых изменений не произойдет. Выберите другой автомобиль и затем снова первоначальный. Теперь вы заметите обновленное значение. Для пользователя такое поведение не особенно подходит.

Добавьте обработчик события Click для кнопки btnAddCar:

  Click="BtnAddCar_OnClick" />

В обработчике события BtnAddCar_OnClick добавьте новую запись в список Car:

private void BtnAddCar_Click(object sender, RoutedEventArgs e)

{

  var maxCount = _cars?.Max(x => x.Id) ?? 0;

  _cars?.Add(new Car { Id=++maxCount,Color="Yellow",Make="VW",PetName="Birdie"});

}

Запустите приложение, щелкните на кнопке Add Car (Добавить автомобиль) и просмотрите содержимое элемента управления ComboBox. Хотя известно, что в списке имеется три автомобиля, в элементе ComboBox отображаются только два! Чтобы устранить обе проблемы, вы превратите класс Car в наблюдаемую модель и будете использовать наблюдаемую коллекцию для хранения всех экземпляров Car.

<p id="AutBody_Root1262"><strong>Наблюдаемые модели</strong></p>

Проблема с тем, что изменение значения свойства модели не отображается в пользовательском интерфейсе, решается за счет реализации классом модели Car интерфейса INotifyPropertyChanged. Интерфейс INotifyPropertyChanged содержит единственное событие PropertyChangedEvent. Механизм привязки XAML прослушивает это событие для каждого привязанного свойства в классах, реализующих интерфейс INotifyPropertyChanged. Вот как определен интерфейс INotifyPropertyChanged:

public interface INotifyPropertyChanged

{

  event PropertyChangedEventHandler PropertyChanged;

}

Добавьте в файл Car.cs следующие операторы using:

using System.ComponentModel;

using System.Runtime.CompilerServices;

Затем обеспечьте реализацию классом Car интерфейса INotifyPropertyChanged:

public class Car : INotifyPropertyChanged

{

  // Для краткости код не показан.

  public event PropertyChangedEventHandler PropertyChanged;

}

Событие PropertyChanged принимает объектную ссылку и новый экземпляр класса PropertyChangedEventArgs:

PropertyChanged?.Invoke(this,

  new PropertyChangedEventArgs("Model"));

Первый параметр представляет собой объект, который инициирует событие. Конструктор класса PropertyChangedEventArgs принимает строку, указывающую свойство, которое было изменено и нуждается в обновлении. Когда событие инициировано, механизм привязки ищет элементы управления, привязанные к именованному свойству данного объекта. В случае передачи конструктору PropertyChangedEventArgs значения String.Empty обновляются все привязанные свойства объекта.

Вы сами управляете тем, какие свойства вовлечены в процесс автоматического обновления. Автоматически обновляться будут только те свойства, которые генерируют событие PropertyChanged внутри блока set. Обычно в перечень входят все свойства классов моделей, но в зависимости от требований приложения некоторые свойства можно опускать. Вместо инициирования события PropertyChanged непосредственно в блоке set для каждого задействованного свойства распространенный подход предусматривает написание вспомогательного метода (как правило, называемого OnPropertyChanged), который генерирует событие от имени свойств обычно в базовом классе для моделей. Добавьте в класс Car следующий метод:

protected void OnPropertyChanged([CallerMemberName] string propertyName = "")

{

  PropertyChanged?.Invoke(this,

    new PropertyChangedEventArgs(propertyName));

}

Модифицируйте каждое автоматическое свойство класса Car, чтобы оно имело полноценные блоки get и set, а также поддерживающее поле. В случае если значение изменилось, вызовите вспомогательный метод OnPropertyChanged. Вот обновленное свойство Id:

Перейти на страницу:

Похожие книги