В множество колонок объекта DataTable легко добавить вычисляемые колонки, то есть, поля данных, которых в действительности в источнике данных нет, но они вычисляются и добавляются в таблицу на ходу. Это, в частности, можно сделать с помощью объекта DataRelation. Каждый студент сдал какие-то экзамены и они хранятся в связанной таблице Exams. Их количество может отличаться (если нет, то вы сделаете его разным, работая с формой и XML-файлом данных). С помощью объекта DataRelation мы вычислим количество экзаменов для каждого студента и покажем его в отдельной колонке таблицы DataTable, а, следовательно, (благодаря механизму DataBinding) и DataGridView. Добавим в таблицу студентов колонку, отображающую количество сданных ими экзаменов. Это делается удивительно просто.
ds.Tables[0].Columns.Add("ExamsNo", typeof(int), "Count(Child.StudID)");
Эту строку кода следует вставить после того, как в DataSet была добавлена связь между таблицами студентов и экзаменов, но до вызова метода AddStyleStud (иначе наш стиль не подействует на новую колонку). Секрет ее работы состоит в строковой константе "Count(Child.StudID)" (вспомните про роль имен в механизме DataBinding). Она задает значение свойства Expression (вычисляемое выражение), которое имеется в каждом объекте класса DataColumn. Рассмотрим части выражения.
¨ Count() определяет функцию SQL-запроса,
¨ Child определяет множество строк, таблицы Exams, связанных с текущей строкой таблицы студентов,
¨ StudID определяет поле внешнего ключа связи.
Обратите внимание на то, что DataGridView не позволяет редактировать поля данных этой колонки и это правильно. Если вы теперь вызовите метод Save, то данные вычисляемой колонки попадут в XML-файл, что не правильно. Предотвратить это можно, взяв в свои руки процесс записи в файл (работать с методами класса XmlDocument), а не надеяться на мудрость метода WriteXml. Подозреваю, что есть и другие способы решения этой проблемы. Например:
¨ Вместо метода WriteXml класса DataSet использовать метод Serialize класса XmlSerializer.
¨ Для этого придется ввести промежуточный слой: сериализуемые классы Stud и Exam или класс MyDataTable, производный от DataTable.
¨ В промежуточном слое надо пометить исключаемое свойство атрибутом [XmlIgnore], или не иметь его вовсе.
¨ Сериализовывать можно или видоизмененный DataSet, или вспомогательные коллекции, содержащие объекты классов Stud и Exam.
Задание. Добавьте колонку, которая вычисляет средний балл студента.
ds.Tables[0].Columns.Add("Average", typeof(decimal), "Sum(Child.Mark)/Count(Child.StudID)");
Отображение данных в DataGridView и манипуляция данными в DataSet — это две разные функции. DataGridView обеспечивает интерфейс пользователя, а архитектура привязки к данным (data-binding architecture) ADO.NET отслеживает изменение данных в памяти. При этом важно, чтобы изменения данных в DataGridView были всегда синхронизированы с их изменениями в DataSet.
Для отбора и поиска записей в таблице класс DataTable предоставляет метод Select. С его помощью мы можем находить записи (строки) таблицы, удовлетворяющие критерию отбора, задаваемому в параметрах. Метод имеет несколько перегруженных версий. Рассмотрим синтаксис последней, самой мощной из них.
public DataRow[] Select(
string filterExpression, // Критерий фильтрации содержимого
string sort, // Способ сортировки
DataViewRowState recordStates); // Критерий фильтрации состояния строк
Как видите, он возвращает ссылку на генерируемый на ходу массив строк, которые удовлетворяют критерию поиска. Параметры имет следующий смысл:
¨ filterExpression — выражение, определяющее что следует искать. Оно фильтрует записи, отбрасывая те, что не удовлетворяют критерию поиска. Формат выражения сходен с оператором WHERE языка SQL.
¨ sort — строка текста указывающая, как сортировать найденные записи. Ее формат совпадает с тем, что используется оператором ORDER BY выражения SQL.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.