Практическое занятие № 11
Тема: Выполнение сортировки и фильтрации
Цель работы: получить практические навыки по выполнению сортировки и фильтрации данных в разных СУБД
Ход работы
Пусть в СУБД Access спроектирована база данных (скачать). База защищена паролем "rpo" и имеет две таблицы.
Таблица "students", состоит из полей:
| Имя поля | Тип | Размер |
| id_stud | Счетчик | Ключевое |
| fam | Текстовый | 15 |
| imya | Текстовый | 15 |
| otch | Текстовый | 15 |
| finance | Текстовый | 10 (Госзаказ, Контракт) |
| datar | Дата/время | |
| srbal | Числовой | Одинарной точности с плавающей точкой. Значение по умолчанию - 0 |
| foto | Поле OLE | |
| id_grup | Числовой | Внешний ключ для связи с таблицей groups |
Таблица "groups", состоит из полей:
|
Имя поля |
Тип |
Размер |
| id_grup | Счетчик | Ключевое |
| grupa |
Текстовый |
30 |
В программе на C# выполните подключение базы данных
Указания: на панели "Источники данных" щелкните на кнопке "Добавить новый источник данных" (если панель не отображается, то выбери команду меню "Данные - Показать источники данных"). Запуститься мастер создания подключения к БД. В окне выберите значение "База данных", затем значение "Набор данных". На следующем шаге щелкните на кнопке "Создать подключение". В новом окне Вам будет предложено подключить файлы БД SQL Server. Щелкните на кнопке "Изменить" и выберите формат БД "Microsoft Access". После этого укажите нужный файл БД (путь к файлу не удаляйте, среда C# самостоятельно скопирует указанный файл в папку проекта и скорректирует путь к нему). Так как база защищена паролем, то щелкните на кнопке "Дополнительно" и в строке "Jet OLEDB: DataBase Password" укажите пароль "rpo". Для проверки соединения щелкните на кнопке "Проверить подключение". После задания всех параметров мастер предложит выбрать способ сохранения пароля к БД: не включать в строку подключения или включать в строку подключения. Выберите первый вариант для безопасности.
После задания параметров БД при переходе на следующий шаг мастера появится запрос на копирование файла БД в папку с проектом, подтвердите эту операцию.
На следующем шаге мастер предложит сохранить строку подключения в файл конфигурации приложения. Так как пароль доступа не включен в строку подключения, то можете согласиться на сохранение в файл.
На следующем шаге выберите обе таблицы students и groups, с которыми планируете работать в проекте, и щелкните "Готово".
Сразу нужно настроить поведение полей-счетчиков в таблицах. В окне "Источники данных" щелкните на кнопке "Изменить набор данных в конструкторе". Отобразится структура таблиц. Выделите поле id_stud в таблице students и измените свойства: AutoIncrementSeed = 1, AutoIncrementStep = 1. Выделите поле id_grup в таблице groups и измените свойства: AutoIncrementSeed = 1, AutoIncrementStep = 1.
Создайте программу для работы с данными таблицы. При этом форма должна иметь вид:

Указания: для формы задайте свойства: Caption=Студенты, Position=DesktopCenter, Borderstyle=bsSingle (нерастягиваемая форма), MiximizeBox = false (нет кнопки разворачивания окна), Size-Height=390 (высота, вы можете указать свое значение).
Для подключения таблицы students нанесите на форму компонент DataRowView. Появится окно, в котором нужно указать подключаемую таблицу students. На форме появятся дополнительные компоненты для работы с таблицей: bazaDataSet - для доступа к подключению, studentsBindingSource - для работы с набором данных, studentsTableAdapter - для работы с копией таблицы БД. Для сетки задайте свойства: AllowUserToAddRows = false (запрет добавления новых строк в сетке), ReadOnly=true, AllowUserToDeleteRows = false (запрет на удаление данных в сетке без подтверждения), AlternatingRowsDefaultCellStyle - BackColor = серый (цвет фона четных строк сетки), AutoSizeColumnsMode=Fill (ширина колонок подстраивается под размер сетки).
Для настройки параметров колонок сетки откройте ее свойство Columns. Вы увидите список всех ее колонок. Колонку id_stud сделайте невидимой (Visible=false), для остальных колонок в свойстве HeaderText укажите названия как на рисунке, поле id_group разместите после поля datar и настройте свойство HeadetText="Группа".
Для выравнивания текста по центру в заголовках колонок сетки и во всех ее ячейках, для сетки задайте свойства: ColumnHeadersDefaultCellStyle.Alignment = MiddleCenter, DefaultCellStyle.Alignment = MiddleCenter. Для выравнивания текста по левому краю в колонке "Группа" откройте свойство сетки Columns, выделите колонку "Группа" и задайте свойство DefaultCellStyle.Alignment = MiddleLeft.
Для подключения таблицы groups нанесите на форму компонент DataRowView. Появится окно, в котором нужно указать подключаемую таблицу groups. На форме появятся дополнительные компоненты для работы с таблицей: groupsBindingSource - для работы с набором данных, groupsTableAdapter - для работы с копией таблицы БД. Так как таблица groups не будет отображаться в сетке, а будет использоваться для выпадающего списка, то сетку удалите. В выпадающем списке названия групп будет отображать в алфавитном порядке. Для этого для компонента groupsBindingSource задайте свойство Sort = grupa (имя поля для сортировки.)
Если запустить программу на выполнение, то сетка будет пустой, потому что в строке соединения мы не сохранили пароль к БД и подключение не установлено.
Для формы откройте событие Load. В этом событии будут находится две команды Fill(), загружающие копии таблиц в компоненты TableAdapter. Над этими командами добавьте команду подстановки пароля в строку соединения:
Properties.Settings.Default["BazaConnectionString"] += ";Jet OLEDB:Database Password=rpo";
Кнопка "Фильтрация" увеличивает форму по высоте и отображает поля для ввода параметров поиска. Такая форма будет иметь вид:

Указания: на форму добавьте кнопку и задайте свойство Text=Фильтрация. Кнопка должна увеличить высоту формы и отобразить поля для ввода ключей поиска данных. Для этого в событии Click кнопки введите код:
void Button1_Click(object sender, EventArgs e)
{
//увеличиваем высоту формы (можете задать свое значение)
Height = 525;
//центрируем
форму по вертикали, сохраняя ее начальное положение по центру экрана
Top = (Screen.PrimaryScreen.Bounds.Height - Height) / 2;
//блокируем кнопку "Фильтрация"
button1.Enabled=false;
}
Пользователь может произвольно заполнять нужные поля для поиска. Поля "Дата от" и "Дата до" заполняются с помощью календаря (DateTimePicker). Поиск по дате рождения и окладу выполняется по диапазону значений.
Указания: увеличьте высоту формы, задав для нее свойство Size - Height=550. На форму нанесите компоненты textBox и компоненты comboBox (для поиска по группе и финансированию).
Разместите и подпишите их так, как показано на рисунке в задании.
Компонент comboBox для поиска по группе будем заполнять значениями из таблицы справочника groups. Для этого задайте для него свойства: DataSource = groupsBindingSource, DisplayMember = grupa (названия групп будут отображаться в списке), ValueMember = id_grup (фактический номер группы, используемый в условии поиска). Обратите внимание, что таблица-справочник groups обязательно должна содержать запись с пустой группой. Это пустое значение будет использоваться для очистки условия в выпадающем списке. В нашей БД это условие выполнено и, так как мы задали сортировку данных в компоненте groupsBindingSource по полю grupa, то пустое значение окажется в списке первым.
Компонент comboBox для поиска по финансированию будет содержать фиксированный набор значений. Для этого в его свойстве Items введите значения: Пустая строка, Госзаказ, Контракт. пустая строка должна идти первой. Она нужна для очистки условия в выпадающем списке.
Для полей задания диапазона дат нужно использовать компоненты DateTimePicker. Добавьте на форму два компонента DateTimePicker, задайте им такой же размер, который имеют соответствующие компоненты textBox, и задайте им свойство Visible=false.
Для комбинации календаря с полем для текстового поля "Дата от" в событии Enter введите код:
void textBox4_Enter(object sender, EventArgs e)
{
//делаем календарь видимым
dateTimePicker1.Visible=true;
//ставим курсор в поле с календарем
dateTimePicker1.Focus();
}
Для календаря, соответствующего полю "Дата от", в событии Validated введите код:
void DateTimePicker1_Validated(object sender, EventArgs e)
{
//делаем календарь невидимым
dateTimePicker1.Visible=false;
//в поле записываем выбранную дату
textBox5.Text=dateTimePicker1.Value.ToString("dd/MM/yyyy");
}
Аналогично для поля "Дата до" в событии Enter введите код:
void TextBox5_Enter(object sender, EventArgs e)
{
//делаем календарь видимым
dateTimePicker2.Visible=true;
//ставим курсор в поле с календарем
dateTimePicker2.Focus();
}
Аналогично для календаря, размещенного над полем "Дата до", в событии Validated введите код:
void DateTimePicker2_Validated(object sender, EventArgs e)
{
//делаем календарь невидимым
dateTimePicker2.Visible=false;
//в поле записываем выбранную дату
textBox5.Text=dateTimePicker2.Value.ToString("dd/MM/yyyy");
}
После ввода кодов обработчиков событий разместите календари DateTimePicker поверх соответствующих текстовых полей.
Кнопка "Отобрать" фильтрует данные в таблице.
Указания: нанесите на форму кнопку и задайте свойство Text=Отобрать. Кнопка отбирает в сетке записи в соответствии с заданными условиями поиска. Для кнопки введите код:
void Button2_Click(object sender, EventArgs e)
{
//переменная для формирования условия поиска
string s = "";
//задаем условие поиска для поля "fam" (текстовое)
if (textBox1.Text != "")
s += "fam like '" + textBox1.Text + "%'";
//задаем условие поиска для поля "imya" (текстовое)
if (textBox2.Text != "")
if (s != "")
s += " and imya like '" + textBox2.Text + "%'";
else
s += "imya like '" + textBox2.Text + "%'";
//задаем условие поиска для поля "otch" (текстовое)
if (textBox3.Text != "")
if (s != "")
s += " and otch like '" + textBox3.Text + "%'";
else
s += "otch like '" + textBox3.Text + "%'";
//задаем условие поиска для поля "grup" (текстовое)
//выпадающий список заполняется на основе таблицы-справочника,
//значит значение выбранного элемента берется из свойства SelectedValue
if (comboBox1.Text != "")
if (s != "")
s += " and id_grup = " + comboBox1.SelectedValue.ToString();
else
s += "id_grup = " + comboBox1.SelectedValue.ToString();
//задаем условие поиска для поля "finance" (текстовое)
//выпадающий список заполняется фиксированным набором значений,
//значит значение выбранного элемента берется из свойства Text
if (comboBox2.Text != "")
if (s != "")
s += " and finance like '" + comboBox2.Text + "%'";
else
s += "finance like '" + comboBox2.Text + "%'";
//задаем условие поиска для поля "datar" (дата от) (дата/время)
//обратите внимание на то, что содержимое поля textBox4 конвертируется в дату,
//а затем в текст в формате #MM/dd/yyyy#
if (textBox4.Text != "")
if (s != "")
s += " and datar >=" + Convert.ToDateTime(textBox4.Text).ToString("#MM'/'dd'/'yyyy#");
else
s += "datar >=" + Convert.ToDateTime(textBox4.Text).ToString("#MM'/'dd'/'yyyy#");
//задаем условие поиска для поля "datar" (дата до) (дата/время)
//обратите внимание на то, что содержимое поля textBox5 конвертируется в дату,
//а затем в текст в формате #MM/dd/yyyy#
if (textBox5.Text != "")
if (s != "")
s += " and datar <=" + Convert.ToDateTime(textBox5.Text).ToString("#MM'/'dd'/'yyyy#");
else
s += "datar <=" + Convert.ToDateTime(textBox5.Text).ToString("#MM'/'dd'/'yyyy#");
//задаем условие поиска для поля "srbal" (ср.балл от) (числовое)
if (textBox6.Text != "")
if (s != "")
s += " and srbal >=" + textBox6.Text;
else
s += "srbal >=" + textBox6.Text;
//задаем условие поиска для поля "srbal" (ср.балл до) (числовое)
if (textBox7.Text != "")
if (s != "")
s += " and srbal <=" + textBox7.Text;
else
s += "srbal <=" + textBox7.Text;
//проверяем, задано ли условие фильтрации
if (s!="")
//применяем условие как фильтр для отбора
studentsBindingSource.Filter = s;
}
Кнопка "Показать все" очищает все поля для ввода условий фильтрации и отображает в сетке все записи.
Указания: добавьте на форму кнопку и задайте свойство Text=Показать все. Для кнопки напишем код:
void Button3_Click(object sender, EventArgs e)
{
//очищаем все текстовые поля
textBox1.Text = textBox2.Text = textBox3.Text = textBox4.Text =
textBox5.Text = textBox6.Text = textBox7.Text = "";
//в выпадающих списках переходим на первый элемент (на пустые строки)
comboBox1.SelectedIndex = comboBox2.SelectedIndex = 0;
//удаляем фильтр для набора данных
studentsBindingSource.Filter = null;
//ставим курсор в первое поле ввода условий фильтрации
textBox1.Focus();
}
Кнопка "Скрыть" возвращает форму в начальный размер по высоте.
Указания: нанесите на форму кнопку и задайте свойство Text=Скрыть. Для кнопки напишите код:
void Button4_Click(object sender, EventArgs e)
{
//возвращаем исходную высоту формы (у вас может быть другое значение)
Height = 390;
//центрируем форму по вертикали, сохраняя ее начальное положение по центру экрана
Top = (Screen.PrimaryScreen.Bounds.Height - Height) / 2;
//разблокируем кнопку "Фильтрация"
button1.Enabled=true;
}
Реализуйте возможность удаления дат из полей на форме поиска.
Указания: при задании условий для фильтрации пользователь может свободно вводить и удалять данные во всех полях, кроме "Дата от" и "Дата до". При установке в эти поля курсора, появляется календарь, что делает невозможным удаление дат вручную. Для решения проблемы справа от полей с датами нанесите на форму две кнопки и задайте свойство Text=X. Для кнопок напишем код очистки нужных полей.
private void button5_Click(object sender, EventArgs e)
{
textBox4.Text = "";
}
private void button6_Click(object sender, EventArgs e)
{
textBox5.Text = "";
}