Механизм привязки данных (DataBinding), страница 5

¨  Привяжем внутреннюю коллекцию элементов ComboBox к данным той же таблицы States. Здесь есть один момент, на который важно обратить внимание. ComboBox показывает (displays) одно, а возвращает в качестве выбранного элемента (при обращении к свойству SelectedValue) — другое. Такое поведение достигается раздельной установкой свойств DisplayMember и ValueMember.

comboStates.DataSource = dt;          // Привязываем comboStates к DataTable

comboStates.DisplayMember = "Name"; // Показываем поле States.Name

comboStates.ValueMember = "Code";     // Выбираем поле States.Code (первичный ключ таблицы)

Список отображает поле States.Name, а при выборе строки возвращает поле States.Code. Запустите и проверьте. Изменения текущих позиций в обоих элементах синхронизированы. Это обеспечено правильным выбором синхронизатора позиций — CurrencyManager. Для сравнения (временно) замените синхронизатор, заменив одну строку кода:

gridStates.DataSource = dt;

двумя строками:

gridStates.DataSource = ds;

gridStates.DataMember = dt.TableName;

и проверьте работу элементов при перемещении по строкам DataGridView. Теперь сихронизация отсутствует, так как работают разные объекты типа CurrencyManager. Вернитесь к прежнему варианту синхронизации и привяжите окна редактирования к колонкам (точнее, текущим полям данных) таблицы States (Simple DataBinding).

tStateID.DataBindings.Add ("Text", dt, "ID");

tStateName.DataBindings.Add ("Text", dt, "Name");

tStateCode.DataBindings.Add ("Text", dt, "Code");

Вновь проверьте функционирование элементов.

¨  Добавьте привязку данных для отслеживания текущей позиции в ComboBox (Simple Databinding).

lblNum.DataBindings.Add ("Text", comboStates, "SelectedIndex");

¨  C помощью команды AddClass введите в проект новый класс Customer.

public class Customer

{

private string name;

private string stateCode;

public Customer (string name, string stateCode)

{

this.name = name;

this.stateCode = stateCode;

}

public string Name

{

get { return name; }

set { name = value; }

}

public string StateCode

{

get { return stateCode; }

set { stateCode = value; }

}

public string Display { get { return this.ToString(); } }

public override string ToString () { return name + ",  " + stateCode; }

}

¨  В теле метода BindToTable создайте объект класса Customer и привяжите поле редактирования tCustomer к свойству Display объекта класса Customer.

Customer cust = new Customer ("Joe Doe", null);

tCustomer.DataBindings.Add ("Text", cust, "Display");

Запустив приложение, убедитесь, что последняя привязка данных работает, но не следит за изменением значений свойства stateCode. Для того, чтобы включить реакцию на изменение свойств текущей строки таблицы или элемента списка, надо заставить объекты класса Customer уведомлять (notify) своих клиентов об изменении свойств. Одним из способов внесения такого поведения является реализация интерфейса INotifyPropertyChanged. Рассмотрим, как добавить эту функциональность в класс Customer.

¨  Измените декларацию класса.

public class Customer : INotifyPropertyChanged

Интерфейс INotifyPropertyChanged заявляет всего одно событие PropertyChanged, делегатный тип которого должен быть PropertyChangedEventHandler.

¨  Вставьте внутрь класса Customer объявление события такого типа.

public event PropertyChangedEventHandler PropertyChanged;

Это событие должно быть возбуждено (вспомните, как произносят это слово юристы — с ударением на у) при каждой попытке изменить свойство StateCode. Очевидно, это происходит в ветви set указанного свойства.

¨  Измените алгоритм ветви set свойства StateCode:

if (PropertyChanged != null)

PropertyChanged (this, new PropertyChangedEventArgs ("StateCode"));