Практическое занятие № 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 = "";

}