ADO.NET. Управление базами данных. Связь по схеме OLE DB провайдера. Коррекция стилей DataGridView, страница 17

   ds.RejectChanges();

  }

·  Добавьте один обработчик события RowUpdated, который будет обслуживать оба адаптера связи.

  void adapter_RowUpdated(object sender, OleDbRowUpdatedEventArgs e)

  {

   string id = sender == daStud ? "StudID" : "ExamID";

   if (e.Status == UpdateStatus.Continue && e.StatementType == StatementType.Insert)

   {

    e.Row[id] = (int)(new OleDbCommand("SELECT @@IDENTITY", cn)).ExecuteScalar();

    e.Row.AcceptChanges();

   }

  }

Анализируя параметр sender, мы узнем, какой из двух адаптеров пытается добавить новую строку. В метод UpdateDB внесите изменения, как показано ниже. При нажатии кнопки Save адаптеры связи с СУБД пытаются обновить данные обех таблиц.

void UpdateDB()

{

  try

  {

   daStud.Update(ds.Tables[0]);

   daExam.Update(ds.Tables[1]);

  }

  catch (Exception ex) { MessageBox.Show(ex.Message); }

}

Запустите приложение и убедитесь, что данные подчиненной таблицы отслеживают изменение позиции в gridStud, а, значит (благодаря DataBinding), и в таблице ds.Tables[0]. Секрет синхронизации данных, отображаемых вторым DataGridView (gridExam), при перемещении по строкам первого, кроется в строке текста, используемой механизмом DataBinding. Эта строка (DataMember) сейчас задана неявно, но ее можно задать и явно. Рассмотрим этот способ.

·  Временно закомментируйте две строки кода, которые задают свойства DataSource и вставьте четыре строки, которые приведены ниже.

   gridStud.DataSource = ds;

   gridStud.DataMember = "Studs";

   gridExam.DataSource = ds;

  gridExam.DataMember = "Studs.StudsExams";

·  Проверьте работу приложения и убедитесь, что синхронизация таблиц не нарушилась.

Настоящий вариант синхронизации обходится без объектов BindingSource, они сейчас не работают. Повторю, еще раз: секрет снхронизации состоит в том, что данные gridExam фильтруются с помощью DataRelation и это определено строкой текста "Studs.StudsExams". Заметим, что обе строки текста (DataMember) можно вычислить.

   gridStud.DataMember = ds.Tables[0].TableName; 

   gridExam.DataMember = ds.Tables[0].TableName + "." + ds.Relations[0].RelationName;

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

   gridStud.DataSource = bsStuds;

   gridExam.DataSource = bsExams;

Объекты BindingSource тоже имеют свойства DataMember (типа string), которые используются в механизме привязки к данным. Первый DataGridView (gridStud) привязан к первой таблице, а второй — к связи, существующей между первой и второй таблицами. Саму связь (DataRelation) мы создали и ввели в DataSet заранее.

Объекты bsStuds и bsExams можно использовать для отслеживания текущей позиции в DataGridView (на экране). Она привязана к строке таблицы DataTable (в памяти). Для отображения данных текущей строки в каком-то другом элементе формы, можно привязать его к данным синхронизатора. Предположим, например, что вы нашли на форме место для метки lblName (объекта класса Label). Теперь вы можете привязать ее свойство Text к данным bsStuds (включить Simple DataBinding).

lblName.DataBindings.Add("Text", bsStuds, "Name");

Текст метки будет следить за полем Name активной строки таблицы студентов. При этом нам не надо вводить никаких реакций на события в gridStud. Нужная реакция уже присутствует внутри механизма DataBinding. Для иллюстрации сложной привязки к данным (Complex DataBinding) можно добавить на форму элемент, способный отображать коллекцию объектов, например ListBox, и привязать его к данным синхронизатора bsExams.

listExam.DataSource = bsExams; // Установка свойства DataSource объекта listExam класса ListBox

listExam.DisplayMember = "Course"; // Отображаемое свойство

Рисунок выше иллюстрирует сказанное. Вы видите, что listExam содержит список экзаменов текущего студента, определяемого активной строкой gridStud. Выделенный элемент списка следит за активной строкой gridExam. Над списком вы видите метку lblName, которая привязана к данным первой таблицы.