Обратите внимание на массу ресурсов (картинок), которые студия автоматически добавила в проект (см. файл MainForm.resx). Всю эту работу можно (в качестве полезного упражнения) сделать и вручную, но она потребует от вас заметных усилий. Технология работы с ресурсами — это особая статья трудозатрат программиста, она требует большого внимания и осторожности, так как легко подпортить уже работающий проект.
Важно помнить, что ресурсы бывают двух типов: внедряемые в файл ресурсов (Embedded in .resx) или подключаемые при компиляции (Linked at compile time). Внедряемые ресурсы в конце концов попадают в exe-файл, их нельзя редактировать и поэтому лучше использовать в случаях, кода вы не хотите, чтобы кто-либо, кроме вас, мог изменить облик приложения. Подключаемые ресурсы хранятся в виде отдельных файлов проекта (например в формате jpg), которые легко заменить в уже готовом проекте.
Итак, навигатор связывания BindingNavigator готов к работе и ждет, когда его подключат. Сделайте это одной строкой кода, местоположение которой вычислите с помощью логики использования навигатора.
bn.BindingSource = bsStuds;
Вновь проверьте работу приложения и убедитесь, что механизм DataBinding реализует желаемую синхроизацию таблиц, то есть, выборочный показ экзаменов.
Недостаток в логике работы приложения обнаруживается при вводе новых записей в первую, родительскую таблицу. Вторая таблица exams является дочерней по отношению к первой и связана с ней по ключевым полям (колонкам ID и StudID). При вводе новой записи в первую таблицу, вторая таблица ведет себя инертно — в ней не появляются новые строки со списком экзаменов для нового студента. Хочется это исправить и автоматизировать процесс появления строк, отображающих весь набор экзаменов.
Очевидно, что добавление экзаменов надо делать в ответ на событие, которое соответствует появлению нового студента. В документации по классам библиотеки .NET Framework находим, что класс DataTable способен обработать два события (RowChanging и RowChanged), которые прямо связаны с нашим намерением. Первое происходит в момент изменения строки таблицы, а второе — после того, как изменения в строке успешно завершились. Выбираем второе и вводим в класс формы реакцию на него. Это делается стандартным способом — добавлением делегата в список делегатов события RowChanged. Введите изменения в метод InitDataSet, как показано ниже.
//=== Добавляем адрес функции обработки события в коллекцию делегатов, поддерживаемую событием RowChanged
studs.RowChanged += new DataRowChangeEventHandler(studs_RowChanged);
Если вы правильно манипулировали механизмом IntelliSense при вводе предыдущего оператора (вводе, а не копировании), то заготовка метода studs_RowChanged класса MainForm, реагирующего на событие добавления новой записи, была автоматически создана редактором студии. Если заготовки нет, то вводите ее руками, или научитесь работать с IntelliSense и повторите ввод.
Просмотрите код заготовки. В качестве параметра она получает ссылку на объект вспомогательного класса DataRowChangeEventArgs, который содержит важную информацию о конкретном типе изменения. Для того, чтобы узнать какие изменения в принципе отслеживаются, смотрите справку по перечислению DataRowAction. Мы используем эту информацию для фильтрации только одного типа изменений (Add).
void studs_RowChanged(object sender, DataRowChangeEventArgs e)
{
DataTable exams = ds.Tables[1]; // Ссылка на связанную таблицу
if (e.Action == DataRowAction.Add) // Если в первой таблице появилась новая строка
{
for (int j = 0; j < courses.Length; j++) // Создаем 4 записи во второй таблице
{
DataRow row = exams.NewRow();
row["StudID"] = e.Row["ID"];// Первичный и связанный ключи должны сопадать
row["Course"] = courses[j]; // Массив с именами предметов должен существовать
row["Credit"] = false;
row["Date"] = DBNull.Value; // Значение DBNull соответствует незаполненным полям
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.