БлогNot. Заполняем таблицу DataGridView из кода и обрабатываем событие CellFormatting

Заполняем таблицу DataGridView из кода и обрабатываем событие CellFormatting

Предыдущая заметка по работе с таблицами DataGridView в среде Visual Studio (VS 2015, C++/CLI) находится вот здесь. А в этой статье мы покажем, как можно формировать таблицы построчно и наиболее простым способом "заставлять" пользователя соблюдать формат столбцов при вводе - заменяя величину в ячейке на значение по умолчанию, если введено что-то не то.

Проект Windows Forms создан как обычно, в верхнюю часть формы перетащим контейнер Panel установим ему привязку Dock = Top, а положение Location = 0; 0 .

На панели разместим 2 кнопки размером Size = 32; 32 которые получат наименования button1, button2, изобразим на них подписи (свойство Text) "+" и "-" (добавление и удаление записи).

Ниже панели добавим табличный элемент данных DataGridView, установим у него свойство Dock = Fill. Все остальные свойства таблицы настроим программно, удобнее написать для этой цели отдельный метод, который вызовется из обработчика события Load формы, вот обе функции:

private: System::Void setupDataGridView (DataGridView ^d) {
  //Настроить свойства таблицы удобней отдельным методом
  d->ColumnCount = 5;
  d->ColumnHeadersDefaultCellStyle->BackColor = Color::Navy;
  d->ColumnHeadersDefaultCellStyle->ForeColor = Color::White;
  d->GridColor = Color::Black;
  d->ColumnHeadersDefaultCellStyle->Font = 
   gcnew System::Drawing::Font (d->Font,FontStyle::Bold);
  d->Name = L"Таблица";
  d->Location = Point (2,this->panel1->Bottom+2);
  d->Size = System::Drawing::Size 
   (this->ClientSize.Width-4, this->ClientSize.Height - 4);
  d->Columns[0]->Name = L"Id";
  d->Columns[1]->Name = L"Категория";
  d->Columns[2]->Name = L"Название";
  d->Columns[3]->Name = L"Дата";
  d->Columns[4]->Name = L"Стоимость";
  d->SelectionMode = DataGridViewSelectionMode::FullRowSelect;
  d->MultiSelect = true;
  //Также добавим столбец "только для чтения":
  DataGridViewColumn ^column = gcnew DataGridViewColumn();
  column->HeaderText = L"Итого";
  column->ValueType = Int32::typeid; //в C++/CLI нет typeof()
  column->ReadOnly = true; //Столбец "только для чтения"
  DataGridViewCell ^cell = gcnew DataGridViewTextBoxCell();
  cell->Style->BackColor = Color::Wheat;
  column->CellTemplate = cell;
  d->Columns->Add(column);
 }

private: System::Void MyForm_Load(System::Object^  sender, System::EventArgs^  e) {
  setupDataGridView (this->dataGridView1); //Настроить таблицу при загрузке формы
  array <String ^> ^row0 =
    { "0","Пищевые продукты","Молоко","18/11/2018","60" };
  dataGridView1->Rows->Add(row0); //Как заполнить таблицу из кода, пример
  array <String ^> ^row1 =
    { "1","Пищевые продукты","Хлеб","17/11/2018","35,50" };
  dataGridView1->Rows->Add(row1);
}

Кроме того, функция MyForm_Load показывает, как добавить в таблицу "предустановленные" записи, сохранённые в массиве строк.

Кнопке 1 останется просто добавить пустую запись:

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
 dataGridView1->Rows->Add(1); //Просто добавить строку
}

Кнопка 2 реализует короткий код для удаления выделенной строки, если таковая есть:

private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
 //Просто удалить выделенные строки
 if (dataGridView1->SelectedRows->Count > 0 &&
  dataGridView1->SelectedRows[0]->Index != 
  dataGridView1->Rows->Count-1) { 
    dataGridView1->Rows->RemoveAt(
     dataGridView1->SelectedRows[0]->Index);
 }
}

Наконец, для настройки и проверки "на лету" формата данных в столбцах таблицы напишем обработчик её события CellFormatting.

Мы не будем мучить пользователя всплывающими сообщениями, а просто станем заменять "неправильные" числа на значения по умолчанию.

Покажем для примера обработку столбцов "Id" (идентификатор, целое число), "Дата" (вида ДД.ММ.ГГГГ) и "Стоимость" (вещественные числа с 2 знаками в дробной части), другие типы данных можно обработать по аналогии.

Мы не требуем обязательной уникальности значений в столбце id, их можно обновлять, например, при программном заполнении столбца "только для чтения" Итого.

private: System::Void dataGridView1_CellFormatting(System::Object^  sender, 
 System::Windows::Forms::DataGridViewCellFormattingEventArgs^  e) {
 //Для настройки формата столбцов напишем обработчик этого события
 if (e) {
  if (dataGridView1->Columns[e->ColumnIndex]->Name == L"Id") {
   //Для id:
   if (e->Value) try {
    int n = Int32::Parse(e->Value->ToString());
    e->Value = String::Format("{0:d}", n);
   }
   catch (FormatException ^) {
    e->Value = String::Format("{0:d}", e->RowIndex);
    e->FormattingApplied = true;
   }
  }
  //Для корректного вида даты:
  if (dataGridView1->Columns[e->ColumnIndex]->Name == L"Дата") {
   if (e->Value) try {
    e->Value = DateTime::Parse(e->Value->ToString()).ToShortDateString();
    e->FormattingApplied = true;
   }
   catch (FormatException ^) { e->Value = "01.01.1970"; }
  }
  //Для вещественного значения с 2 знаками в дробной части:
  if (dataGridView1->Columns[e->ColumnIndex]->Name == L"Стоимость") {
   if (e->Value) try {
    e->Value = String::Format("{0:N2}", Double::Parse(e->Value->ToString()));
   }
   catch (FormatException ^) { e->Value = "0,00"; }
  }
 }
}

Этот маленький метод будет просто обрабатывать событие DataError:

private: System::Void dataGridView1_DataError(System::Object^  sender, 
 System::Windows::Forms::DataGridViewDataErrorEventArgs^  e) {
 MessageBox::Show (e->Exception->ToString());
}

Вот что получилось:

скриншот этого примера
скриншот этого примера

 Скачать этот проект Visual Studio 2015 в архиве .zip, развернуть, не создавая новой папки (7 Кб)

Можно подойти к задаче проверки корректности ввода в ячейки DataGridView и по-другому - создать ячейку-образец (тип DataGridViewCell), настроить ей свойство стиля Style и установить в качестве шаблона (свойство CellTemplate) для отдельно созданного столбца (тип DataGridViewColumn).

Многие полезные свойства можно указать и непосредственно для столбца, например "только чтение" (ReadOnly), ограничение на тип вводимой величины (ValueType) и т.д.

Ниже показана изменённая функция setupDataGridView, иллюстрирующая этот подход. Кроме того, для перехвата ошибок ввода данных следует написать обработчик события DataError для нашего DataGridView и, конечно, изменить метод button1_Click, так как показанный в примере столбец таблицы - единственный в ней.

private: System::Void setupDataGridView(DataGridView ^d) {
  DataGridViewColumn ^column = gcnew DataGridViewColumn();
  column->HeaderText = L"Столбец";
  column->ValueType = Int32::typeid;
  DataGridViewCell ^cell = gcnew DataGridViewTextBoxCell();
  cell->Style->BackColor = Color::Wheat;
  column->CellTemplate = cell;
  d->Columns->Add(column);
}

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
  dataGridView1->Rows->Add(1);
}

private: System::Void dataGridView1_DataError(System::Object^  sender, 
                        System::Windows::Forms::DataGridViewDataErrorEventArgs^  e) {
 MessageBox::Show (e->Exception->ToString());
}

20.11.2018, 10:13 [8219 просмотров]


теги: программирование c++/cli

К этой статье пока нет комментариев, Ваш будет первым