Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ADO Intro 1 Task.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
555.2 Кб
Скачать

Элемент управления BindingNavigator

BindingNavigator предоставляет стандартные способы управления UI (интерфейсом пользователя) тех элементов формы, которые привязаны к источникам данных (BindingSource). Так как навигатор связывания является довольно сложным компонентом, использующим ресурсы, то вводить его в форму лучше с помощью дизайнера студии. Мы это уже сделали.

Обратите внимание на массу ресурсов (картинок), которые студия автоматически добавила в проект при добавлении навигатора (см. файл FormMain.resx). Всю эту работу можно (в качестве полезного упражнения) сделать и вручную, но она потребует от вас заметных усилий. Технология работы с ресурсами — это особая статья трудозатрат программиста, она требует большого внимания и осторожности, так как легко подпортить уже работающий проект.

Важно помнить, что ресурсы бывают двух типов: внедряемые в файл ресурсов (Embedded in .resx) или подключаемые при компиляции (Linked at compile time). Внедряемые ресурсы в конце концов попадают в exe-файл, их нельзя редактировать и поэтому их лучше использовать в случаях, кода вы не хотите, чтобы кто-либо, кроме вас, мог изменить облик приложения. Подключаемые ресурсы хранятся в виде отдельных файлов проекта (например в формате jpg), их легко заменить в уже готовом проекте и, тем самым, изменить облик приложения.

Итак, навигатор связывания BindingNavigator готов к работе и ждет, когда его подключат. Сделайте это одной строкой кода, местоположение которой вычислите путем анализа логики использования навигатора.

bn.BindingSource = bs[0];

Проверьте работу приложения и убедитесь, что механизм DataBinding реализует желаемую синхроизацию таблиц, то есть, выборочное отображение экзаменов.

Реакции на события в DataTable

Таблица экзаменов является дочерней (подчиненной) по отношению к таблице студентов и связана с ней по ключевым полям (ID и StudID). Такой тип связи часто называют PK-FK (Primary-Key-Forign Key). При вводе новой записи в родительскую таблицу подчиненная таблица ведет себя инертно — в ней не появляются новые строки со списком экзаменов нового студента. Вам придется вручную ввести несколько строк в таблицу экзаменов. Эта рутинная работа будет сильно утомлять не только вас, но и пользователей вашего приложения. В некоторых сценариях работы с данными хочется это исправить и автоматизировать процесс появления строк в подчиненной таблице.

Очевидно, что добавление экзаменов надо делать в ответ на событие, которое соответствует появлению нового студента. В документации по классам библиотеки .NET Framework находим, что класс DataTable способен обработать два события (RowChanging и RowChanged), которые прямо связаны с нашим намерением. Первое происходит в момент изменения строки таблицы, а второе — после того, как изменения в строке успешно завершились. Выбираем второе и вводим реакцию на него в класс формы. Это делается стандартным способом — добавлением делегата в список делегатов события RowChanged. Введите следующий код в начало метода RelateAndBind.

//=== Добавляем адрес функции обработки события в коллекцию делегатов, поддерживаемую событием RowChanged

ds.Tables[0].RowChanged +=

Если вы правильно манипулировали механизмом IntelliSense при вводе предыдущего оператора (вводе, а не копировании текста отсюда), то заготовка метода, реагирующего на событие добавления новой записи, была автоматически создана редактором студии. Если заготовки нет, то введите ее руками, или научитесь работать с IntelliSense и повторите ввод.

Просмотрите код заготовки. Я изменил автоматически сгенерированное имя функции на OnStudsRowChanged. Теперь оно больше соответствует своему назначению. Второй параметр функции (задания делегата) передает ссылку на объект вспомогательного класса DataRowChangeEventArgs, который содержит важную информацию о конкретном типе изменения. Для того, чтобы узнать какие изменения в принципе отслеживаются, смотрите справку по перечислению DataRowAction. Мы используем эту информацию для фильтрации только одного типа изменений (Add).

void OnStudsRowChanged(object sender, DataRowChangeEventArgs e)

{

DataTable exams = ds.Tables[1]; // Ссылка на подчиненную таблицу экзаменов

if (e.Action == DataRowAction.Add) // Если в первой таблице появилась новая строка

{

int num = 0;

foreach (string c in courses) // Массив с именами предметов должен существовать

{

if (num++ != rand.Next(courses.Length))

ds.Tables[1].Rows.Add(CreateRandomExam((int)e.Row["ID"], c));

}

}

}

В нашей версии предполагается, что названия курсов лекций фиксированы и хранятся в массиве текстовых строк courses. Если пользователь вставил в таблицу студентов новую запись (строку), то во второй таблице появляются несколько строк. Для связывания их с родительской строкой первой таблицы (связь типа PK-FK) необходимо правильно установить значение столбца StudID, которое соответствует ключевому полю ID первой таблицы (см. код присвоения e.Row["ID"]).

Попытайтесь отладить приложение и убедиться, что в начальный момент для каждой новой записи, вносимой в первую таблицу, во второй таблице (экзаменов) появляются несколько, связанных с ней, записей.

Это действительно так, если строки добавляются в новую, пустую таблицу. Однако, обработчик события дает сбой при попытке вставить новые строки в старую таблицу, то есть ту, которая восстанавливается из файла. В чем же дело? Попробуйте самостоятельно вычислить причину такого поведения и способ его коррекции.

Вы, вероятно, догадались, что при добавлении строк, которое происходит при чтении данных из файла, возбуждается событие RowChanged и мы автоматически добавляем лишнее множество экзаменов к тем, которые уже есть в файле. Вот один из способов решения этой проблемы. Перед восстановлением всего набора данных из файла, надо выключить реакцию на событие RowChanged и вновь включить ее после прочтения данных из файла. Для этого надо пользоваться операциями –= и += события RowChanged нужной таблицы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]