Табличный редактор XML-файла на Visual Studio
Сохраняем и загружаем данные формата XML, используем набор данных DataSet, добавляем к dataGridView ограничения на вводимые данные, меняем порядок перехода по ячейкам в dataGridView.
В этой недавней статье работа с табличными компонентами библиотеки .NET уже описана, но о некоторых вещах сказано довольно лаконично:
Поэтому следует пользоваться методами объекта DataSet
Дабы не переделывать вполне законченную статью, разработаем отдельное приложение, скажем, простенький табличный редактор успеваемости студенческой группы на основе компоненты DataGridView
.
Создав новый проект Windows Forms с главной формой Form1
, добавим на неё компоненту DataGridView
и растянем на всю форму (свойство Dock = Fill
). Также добавим к проекту контекстное меню contextMenuStrip
с пунктами "Добавить" и "Удалить" и укажем его в свойстве ContextMenuStrip
компоненты dataGridView1
.
Столбцы таблицы (фамилия, 17 граф для оценок или иных отметок, графа "зачёт") создадим программно по событию Load
формы:
BaseName = "table1.xml"; Table = gcnew DataTable(); Set = gcnew DataSet(); dataGridView1->DataSource = Table; Table->Columns->Add ("ФИО"); for (int i=1; i<=17; i++) Table->Columns->Add(""+i); Table->Columns->Add("Итого"); Set->Tables->Add(Table); dataGridView1->DataSource = Set; Table->TableName = "Успеваемость"; if (IO::File::Exists(BaseName) == true) { Set->ReadXml (BaseName); } dataGridView1->DataMember = "Успеваемость"; for(int i=1; i<=17; i++) dataGridView1->Columns[i]->Width = 25;
Перед этим, как и в статье, пропишем в классе формы глобальные величины:
private: String ^ BaseName; //имя файла с данными private: DataTable ^ Table; //таблица с данными private: DataSet ^ Set; //набор для управления данными private: String ^Val; //предыдущее значение из текущей ячейки private: int Column; //текущий столбец private: bool Changed; //признак изменения текущей ячейки
и будем автоматически сохранять данные при выходе из программы (событие FormClosing
):
Table->TableName = "Успеваемость"; Set->WriteXml(BaseName);
По выбору пункта меню "Добавить" выполняется следующее:
DataRow ^newR = Set->Tables["Успеваемость"]->NewRow(); newR[0] = "Студент"; try { int i=dataGridView1->CurrentCell->RowIndex; Set->Tables["Успеваемость"]->Rows->InsertAt(newR,i); Set->Tables["Успеваемость"]->AcceptChanges(); } catch (...) {}
А пункт "Удалить" проще всего запрограммировать так:
try { int i=dataGridView1->CurrentCell->RowIndex; Set->Tables["Успеваемость"]->Rows[i]->Delete(); Set->Tables["Успеваемость"]->AcceptChanges(); } catch (...) { }
Важно, что мы не пытаемся заносить данные "напрямую в таблицу", а добавляем их в набор. Применение AcceptChanges
нужно, чтобы изменение данных немедленно отобразилось в таблице.
Контроль правильности ввода (не более 1 символа в графы отметок, не более 20 символов в графы "ФИО" и "Итого") сделаем следующими обработчиками:
dataGridView1_CellBeginEdit (на начало редактирования):
Column = e->ColumnIndex; //запоминаем столбец Val = dataGridView1->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value->ToString(); //что было в ячейке Changed = false; //ячейка не изменена
dataGridView1_CellValueChanged (по изменению значения в ячейке):
String ^newVal = dataGridView1->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value->ToString(); if (e->ColumnIndex>0 && e->ColumnIndex<18) { if (newVal->Length>1) newVal = Val; } else if (newVal->Length>20) newVal = Val; dataGridView1->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value = newVal;
dataGridView1_EditingControlShowing (для установки своих обработчиков в дополнение к стандартным обработчиками событий компоненты):
if (Column > 0 && Column < 18) { TextBox ^tb = (TextBox^)e->Control; tb->MaxLength = 1; tb->KeyPress += gcnew KeyPressEventHandler(this,&Form1::tb_KeyPress); }
Наша функция – дополнение к обработке KeyPress
- разрешаем буквы, цифры, Bacspace и пробел. Она не член класса формы, просто включить в код:
void tb_KeyPress(System::Object^ sender, System::Windows::Forms::KeyPressEventArgs^ e) { char c = e->KeyChar; if (!(Char::IsLetterOrDigit(c) || c==(char)Keys::Back || c==(char)Keys::Space)) e->Handled = true; //а вот обработчик KeyDown так не сделать }
dataGridView1_CellLeave (покидая ячейку, изменим правила перехода к следующей: по умолчанию – вниз, а мы хотим вправо):
//конечно, "костыль", по идее, надо писать класс-наследник //DataGridView и там управлять клавиатурой if (!Changed) { Changed = true; int c = dataGridView1->CurrentCell->ColumnIndex; if (c == dataGridView1->Columns->Count-1) { SendKeys::Send("{Home}"); } else { SendKeys::Send("{Up}"); SendKeys::Send("{Right}"); } }
Всё это вместе даст более-менее адекватное редактирование. Дело в том, что DataGridView
обрабатывает многие клавиши своими собственными событиями и "не пускает" коды клавиш до уровня KeyPress
или KeyDown
(KeyUp
, вроде, выполняется).
Скачать проект Visual C++ TableEditor4 в архиве .zip (15 Кб)
24.03.2015, 14:11 [10661 просмотр]