- •В ведение в ado.Net
- •Потребитель данных
- •Поставщики данных
- •Источник данных — xml-файл
- •Элементы управления на форме Меню
- •Как устроены планки меню, статуса и панелей инструментов
- •Планка инструментов (ToolStrip)
- •Навигатор связей
- •Контейнер, расщепляющий форму
- •Создание таблиц и внедрение их в DataSet
- •Пояснения
- •Запись и чтение данных
- •Отображение данных связанной таблицы
- •Добавляем ограничение
- •Вторая, подчиненная таблица
- •Автоматическая навигация по записям связанной таблицы
- •Элемент управления BindingNavigator
- •Реакции на события в DataTable
- •Канонизация имен студентов
- •Вычисляемые колонки DataTable (Expression-Based DataColumn Objects)
- •Поиск в таблице DataTable и в компоненте DataGridView
- •Коррекция пользовательского интерфейса
- •Результат поиска
- •Поиск в DataGridView
- •Отбор данных из DataTable и отображение их в ListView
- •Как легко вносятся ошибки
- •Образ таблицы DataView
- •Методы Find и FindRows класса DataView
- •Задание
- •Элемент управления, который позволяет управлять отображением колонок DataGridView
Пояснения
В методе AddStyle мы управляем множеством колонок таблицы, которые отображает grid, а также компонентами его стиля. Здесь опять главную роль играет механизм DataBinding (привязка одного свойства к другому), он включается оператором col.DataPropertyName = dc.ColumnName;.
Индекс таблицы DataSet, которая отображается текущим grid передается параметром. Мы используем его для выбора нужной таблицы, а также для смены цвета фона перемежающихся строк (AlternatingRows).
Заметьте, что для колонки Credit (зачет) вместо объекта DataGridViewTextBoxColumn, мы используем объект класса DataGridViewCheckBoxColumn. Найдите в MSDN справку по всем классам, производным от DataGridViewColumn, и проанализируйте их функциональность. Среди них нет класса CalendarColumn (мы добавили его вручную).
Довольно часто некоторые поля данных надо скрыть, не отображать их на форме (например, поля первичных автоинкрементируемых ключей). Для этого просто не включайте эти поля в множество колонок (объектов DataGridViewColumn), которое добавляется в DataGridView (см. код grid.Columns.Add(col);). В данный момент вы можете добавить код, генерирующий данные таблицы экзаменов, и привязать к ней второй grid (gridExam).
Запись и чтение данных
Класс DataSet значительно упрощает операции записи и чтения данных. Он имеет множество встроенных свойств и методов, поддерживающих управление данными в формате XML. Начнем с метода записи данных WriteXml.
void Save(string fn)
{
if (fn != null && ds.Tables[0].Rows.Count != 0)
{
ds.WriteXml(fn);
SetPath(fn);
}
}
Метод SetPath корректирует значения переменных dirName и fileName.
void SetPath(string fn)
{
Text = fn;
dirName = Path.GetDirectoryName(fn);
fileName = Path.GetFileName(fn);
}
Имя файла fn получим от пользователя с помощью метода FileDlg.
string FileDlg(bool bOpen)
{
FileDialog dlg = bOpen ? (FileDialog)new OpenFileDialog() : (FileDialog)new SaveFileDialog();
dlg.InitialDirectory = dirName;
dlg.Filter = "XML files (*.xml)|*.xml";
dlg.FileName = fileName;
return dlg.ShowDialog() == DialogResult.OK ? dlg.FileName : null;
}
Для обеспечения видимости классов попросите студию вставить недостающие директивы using. Чтение набора данных ds из XML-файла выполним в методе Open.
void Open(string fn)
{
if (fn != null)
{
ds.Clear();
ds.ReadXml(fn);
SetPath(fn);
ds.AcceptChanges();
}
}
Отметьте, что при чтении данных из файла DataSet рождается заново, поэтому старые данные необходимо уничтожить (см. вызов Clear). Создайте папку Data, запустите приложение и сохраните данные в файле Studs.xml. Теперь можно закомментировать строку вызова InitTables и проверить поведение приложения при открытии файла с данными.
Отображение данных связанной таблицы
Связь (relationship) между первой таблицей Studs и второй — Exams имеет вид один ко многим. В реальной базе данных это, как вы знаете, означает, что первичные ключи первой таблицы неоднократно скопированы во вторую и эти копии носят имя связанных ключей (foreign keys). Они ссылаются на строки главной, первичной таблицы, образуя ссылочную целостность данных (referential integrity: каждый экзамен принадлежит какому-то студенту).
Для того, чтобы создать подобную структуру связей в DataSet, необходимо (кроме двух объектов DataTable) добавить объект класса DataRelation. Ссылка на этот объект помещается и хранится в коллекции Relations объекта DataSet. При создании DataRelation надо указать связываемые колонки и задать имя связи. Имя играет решающую роль в настройке механизма DataBinding (так же, как и имена синхронизируемых свойств).
Следующий фрагмент надо добавить в метод RelateAndBind, который вызывается после InitDataSet.
ds.Relations.Add(new DataRelation("StudExam", ds.Tables[0].Columns[0], ds.Tables[1].Columns[1]));
Здесь создается и помещается в коллекцию Relations объект класса DataRelation. Этог код необходим для синхронизации отображения данных связанных таблиц. Суть синхронизации в том, что вторая таблица должна отображать не все экзамены, а только экзамены студента, активного (выбранного) в первой таблице. С этой задачей справится механизм DataBinding, которому надо дать ссылку на DataRelation.
