Практическое занятие № 10
Тема: Приемы работы с сеткой
Цель работы: получить практические навыки по работе с сеткой и выполнению разных операций в ней
Ход работы
Пусть в СУБД 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.
Настройка корректного удаления новых записей
Если добавить новую запись в таблицу и сразу попытаться ее удалить, то часто появляется сообщение об ошибке, связанное с тем, что мастер подключения БД неправильно формирует команды на добавление, обновление и удаление данных. Для решения этой проблемы в окне со структурой таблиц щелкните правой кнопкой на строке "studentsTableAdapter" таблицы students, выберите команду "Настроить". В новом окне щелкните на кнопке "Дополнительно", в следующем окне выключите флажок "Использовать оптимистическую блокировку", щелкните ОК и Готово.
Повторите эти действия для таблицы groups.
Создайте программу для работы с данными таблицы. При этом форма должна иметь вид:

Указания: для формы задайте свойства: Text=Студенты, StartPosition=CenterScreen.
Для подключения таблицы students нанесите на форму компонент DataRowView. Появится окно, в котором нужно указать подключаемую таблицу students. На форме появятся дополнительные компоненты для работы с таблицей: bazaDataSet - для доступа к подключению, studentsBindingSource - для работы с набором данных, studentsTableAdapter - для работы с копией таблицы БД. Для сетки задайте свойства: AllowUserToAddRows = false (запрет добавления новых строк в сетке), ReadOnly=true, AllowUserToDeleteRows = false (запрет на удаление данных в сетке без подтверждения), AutoSizeColumnsMode=Fill (ширина колонок подстраивается под размер сетки), RowHeadersWidth = 25 (уменьшаем ширину колонки с заголовками строк сетки).
Для настройки параметров колонок сетки откройте ее свойство Columns. Вы увидите список всех ее колонок. Колонку id_stud сделайте невидимой (Visible=false), для остальных колонок в свойстве HeaderText укажите названия как на рисунке, поле id_group разместите после поля datar и настройте свойство HeadetText="Группа".
Для выравнивания текста по центру в заголовках колонок сетки и во всех ее ячейках, для сетки задайте свойства: ColumnHeadersDefaultCellStyle.Alignment = MiddleCenter, DefaultCellStyle.Alignment = MiddleCenter. Для выравнивания текста по левому краю в колонке "Группа" откройте свойство сетки Columns, выделите колонку "Группа" и задайте свойство DefaultCellStyle.Alignment = MiddleLeft.
В колонке "Ср.балл" можно вводить только числа. Для этого откройте свойство сетки Columns, выделите колонку "Ср.балл" и задайте свойство DefaultCellStyle.Format = числовой.
Для масштабирования размера сетки при изменении размера формы или раскрытия ее на весь экран привяжите края сетки в краям формы. Для этого в свойстве сетки Anchors активируйте все значения привязки (слева, справа, сверху, снизу).
Для подключения таблицы groups нанесите на форму компонент DataRowView. Появится окно, в котором нужно указать подключаемую таблицу groups. На форме появятся дополнительные компоненты для работы с таблицей: groupsBindingSource - для работы с набором данных, groupsTableAdapter - для работы с копией таблицы БД. Так как таблица groups не будет отображаться в сетке, а будет использоваться для выпадающего списка, то сетку удалите.
Если запустить программу на выполнение, то сетка будет пустой, потому что в строке соединения мы не сохранили пароль к БД и подключение не установлено.
Для формы откройте событие Load. В этом событии будут находится две команды Fill(), загружающие копии таблиц в компоненты TableAdapter. Над этими командами добавьте команду подстановки пароля в строку соединения:
Properties.Settings.Default["BazaConnectionString"] += ";Jet OLEDB:Database Password=rpo";
Добавим в правом нижнем углу формы под сеткой две кнопки. Одна для добавления новой записи, другая - для удаления.
Указания: для кнопок в свойстве Text задайте нужные надписи. Чтобы при изменении размеров формы кнопки всегда оставались в правом нижнем углу, привяжите каждую из них с помощью свойства Anchors, в котором включите нижний и правый край формы.
Для кнопки "Добавить" (button1) напишем код:
private void button1_Click(object sender, EventArgs e)
{
//добавляем новый элемент в набор записей
studentsBindingSource.AddNew();
//кнопку добавления блокируем
button1.Enabled = false;
}
Для кнопки "Удалить" (button2) напишем код:
private void button2_Click(object sender, EventArgs e)
{
//выдаем запрос на удаление
//в тексте запроса указываем ФИО удаляемого студента
//если пользователь подтвердил операцию (DialogResult.Yes)
if (MessageBox.Show("Удалить данные о студенте: "+
(studentsBindingSource.Current as DataRowView)["fam"].ToString()+" "+
(studentsBindingSource.Current as DataRowView)["imya"].ToString()+" "+
(studentsBindingSource.Current as DataRowView)["otch"].ToString() + "?",
"Подтвердите", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
//удаляем текущую запись из набора данных
studentsBindingSource.RemoveCurrent();
//обновляем изменения в таблице БД
studentsTableAdapter.Update(bazaDataSet.students);
}
}
Обычно в программах для работы с БД при переходе между строками сеток автоматически происходит сохранение изменений, если они имели место. В сетке dataGridView это возможность не реализована. Нужно обеспечить такое сохранение данных.
Указания: для набора данных studentsBindingSource в событии CurrentChanged введите код:
private void studentsBindingSource_CurrentChanged(object sender, EventArgs e)
{
//если в наборе данных students имеются изменения
if (bazaDataSet.students.GetChanges() != null)
{
//сохраняем их в таблице БД
Validate();
studentsBindingSource.EndEdit();
studentsTableAdapter.Update(bazaDataSet.students);
}
//кнопку "Добавить" разблокируем
button1.Enabled = true;
}
Реализуем сохранение изменений в БД не только при переходе по строкам сетки, но и при нажатии на Enter после завершения редактирования.
Указания: для реагирования на нажатия клавиш для формы задайте свойство KeyPreview = true.
Так как код сохранения изменений мы уже писали для события CurrentChanged набора данных studentsBindingSource, то в событии KeyUp формы вызовем этот обработчик, чтобы не писать одинаковый код несколько раз:
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
//если нажата клавиша Enter
if (e.KeyCode == Keys.Return)
//вызываем обработчик события перехода по записям набора данных
studentsBindingSource_CurrentChanged(sender, e);
}
Выполните условной форматирование данных в сетке: записи без значения среднего балла окрасить белым цветом, отличники (со средним баллом 5) - светло-зеленым, хорошисты (со средним баллом от 4 и выше) - светло-синим, троечники (со средним баллом от 3 и выше) - светло-коралловым.
Указания: колонка, соответствующая полю srbal, имеет в сетке номер 7 (нумерация с 0, при подсчете нужно также учитывать первую невидимую колонку id_stud).
В событии RowPrePaint сетки введите код;
private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
//если 8-я колонка пуста (соответствует полю "srbal", нумерация с 0)
if (dataGridView1.Rows[e.RowIndex].Cells[7].Value == DBNull.Value)
//закрашиваем белым цветом
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.White;
//если средний балл 5 (отличники)
else if (Convert.ToDouble(dataGridView1.Rows[e.RowIndex].Cells[7].Value) ==5)
//закрашиваем светло-зеленым цветом
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightGreen;
//если средний балл от 4 и выше (хорошисты)
else if (Convert.ToDouble(dataGridView1.Rows[e.RowIndex].Cells[7].Value) >= 4)
//закрашиваем светло-синим цветом
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightBlue;
//иначе (троечники)
else
//закрашиваем светло-коралловым
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightCoral;
}
Для редактирования колонки "Дата рожд." будем использовать специальный тип колонки - DataGridViewCalendarColumn.
Указания: по умолчанию такой тип колонки в сетке отсутствует. Для его использования добавьте в проект файл класса этого типа колонки. Для этого в контекстном меню проекта выберите команду "Добавить - Существующий элемент" и укажите распакованный файл класса. После этого запустите проект для компиляции добавленного файла класса.
Для отображения календаря в колонке сетки откройте свойство сетки Columns и для колонки "Дата рожд." в свойстве ColumnType укажите тип DataGridViewCalendarColumn.
Для редактирования колонки "Финасирование" будем использовать выпадающий список, значения для которого строго фиксированы и не могут вводиться с клавиатуры.
Указания: для фиксированного списка можно задать нужный тип колонки в сетке. Откройте свойство Columns сетки, выберите колонку "Финансирование" и задайте свойство ColumnType = DataGridViewComboBoxColumn. В результате в колонке появится выпадающий список. Теперь в свойстве Items колонки введите допустимые значения: пустая строка, Госзаказ, Контракт. Чтобы выпадающий список появлялся только при входе в ячейку, задайте для колонки свойство DisplayStyle = Nothing.
Для редактирования колонки "Группа" будем использовать выпадающий список, значения для которого будут формироваться из таблицы-справочника "groups".
Указания: откройте свойство Columns сетки, выберите колонку "Группа" и задайте свойство ColumnType = DataGridViewComboBoxColumn. В результате в колонке появится выпадающий список. Для связывания списка с таблицей справочником также для колонки задайте свойства: DataSource = groupsBindingSource, DisplayMember = grupa (названия групп будут отображаться в списке), ValueMember = id_grup (поле, по которому таблица-справочник связана с основной таблицей). Чтобы выпадающий список появлялся только при входе в ячейку, задайте для колонки свойство DisplayStyle = Nothing.
Поле foto нужно настроить так, чтобы изображение внутри ячейки масштабировалось автоматически.
Указания: откройте свойство Columns сетки, выберите поле foto и задайте свойство ImageLayout = Zoom.
При щелчке в поле с фотографией студента должна открываться вторая форма для редактирования изображения.
Указания: в событии CellClick сетки напишите код
void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
//если щелкнули в 9 колонке (foto), но не на ее заголовке
if (e.ColumnIndex==8 && e.RowIndex!=-1)
{
//отображаем форму Form2 (будет создана позже)
Form2 form2 = new Form2();
form2.ShowDialog();
}
}
Вторая форма должна обращаться к источнику данных studentsBindingSource на главной форме. Для этого необходимо присвоить главной форме имя.
Указания: откройте файл проекта Program.cs внести изменения:
после описания класса программы
internal sealed class Program
введите описание глобальной переменной
public static Form1 form1;
Вместо строки
Application.Run(new Form1());
Вставить строки
Program.form1 = new Form1();
Application.Run(form1);
После этого обратится к главной форме можно будет по имени Program.form1. Также для обращения в коде второй формы к компоненту studentsBindingSource измените для него уровень доступа, задайте свойство Modifiers = public.
Создадим форму для редактирования поля foto.

Указания: добавьте новую форму и разместите на ней компонент PictureBox и 2 кнопки. Для формы задайте заголовок (Text), фиксированную границу (FormBorderStyle), отключите кнопки свернуть (MinimizedBox) и развернуть (MaximizedBox) и размещение по центру главной формы при открытии (StartPosition=CenterParent).
Для связывания компонента pictureBox с полем foto в событии Load второй формы введите команду:
void Form2Load(object sender, EventArgs e)
{
pictureBox1.DataBindings.Add(new Binding("Image", Program.form1.studentsBindingSource, "foto", true));
}
Фото будем заполнять с помощью диалога. Нанесите на форму компонент OpenFileDialog и в свойстве Filter укажите допустимые форматы графических файлов:
Графические файлы|*.jpg;*.gif;*.bmp;*.png
Для кнопки "+" напишите код добавления фотографии:
void Button1Click(object sender, EventArgs e)
{
//если файл в диалоге выбран
if (openFileDialog1.ShowDialog()==DialogResult.OK)
{
//в поле pictureBox отображаем выбранный файл
pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);
}
}
Для кнопки "-" напишем код очистки фотографии:
void Button2Click(object sender, EventArgs e)
{
pictureBox1.Image=null;
}
Реализуем в программе возможность настройки и сохранения пути к файлу БД. В качестве способа хранения пути к БД будем использовать файл конфигурации приложения.
Указания: в структуре проекта откройте файл Properties\Setting.settings. В открывшейся таблице со списком параметров добавьте новый: имя = path, тип = string, область = Пользователь.
Внесите в код события Load главной формы изменения. Вместо добавления к строке подключения пароля БД введите фрагмент вида:
private void Form1_Load(object sender, EventArgs e)
{
//описываем переменную для хранения пути к БД
//и считываем в нее значение параметра path
string path = Properties.Settings.Default["path"].ToString();
//если считанный в переменную путь к файлу не существует
if (!File.Exists(path))
//открываем диалог выбора БД
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
//записываем новый путь в переменную
path = openFileDialog1.FileName;
//сохраняем значение переменной в параметр path
Properties.Settings.Default["path"] = path;
Properties.Settings.Default.Save();
}
//если пользователь отказался от выбора БД
else
//завершаем работу приложения
Application.ExitThread();
//настраиваем параметры подключения
//параметру "sotrConnectionString" присваиваем строку подключения
//вместо имени БД подставляем переменную path
Properties.Settings.Default["sotrConnectionString"] = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";Jet OLEDB:Database Password=123";
//отображаем главную форму поверх остальных окон
TopMost = true;
TopMost = false;
//дальше команды Fill() для загрузки данных из таблиц БД
. . .
Для проверки запустите программу на выполнение, указав путь к БД. Закройте программу.
Переименуйте файл БД и запустите программу еще раз. Должен снова появиться диалог выбора файла БД.