БлогNot. Visual C++: табличные компоненты и работа с ними

Visual C++: табличные компоненты и работа с ними

В этой статье мы рассмотрим на простых примерах основные приёмы работы с табличными компонентами .NET, среда для выполнения кода - Visual C++ (Studio) Express 2010 или выше.

Пример 1. Пишем приложение TableEditor1 для редактирования таблицы и сохранения её в формате XML.

На форму добавим компоненту dataGridView1, а объекты DataTable и DataSet создадим программно.

Для этого опишем глобально в классе формы следующие величины:

private: String ^ BaseName;
private: DataTable ^ Table;
private: DataSet ^ Set;

На загрузку формы реализуем такой код (обработчик события Load):

BaseName  = "table.xml";
Table = gcnew DataTable();
Set = gcnew DataSet();
if (IO::File::Exists(BaseName) == false) {
 dataGridView1->DataSource = Table;
 Table->Columns->Add ("Имена");
 Table->Columns->Add("Номера телефонов");
 Set->Tables->Add(Table);
}
else  {
 Set->ReadXml (BaseName);
 String ^ StringXML = Set->GetXml();
 dataGridView1->DataMember = "Название таблицы";
 dataGridView1->DataSource = Set;
}

Перед закрытием формы выполним следующий код (обработчик события FormClosing):

Table->TableName = "Название таблицы";
Set->WriteXml(BaseName);

Данные сохраняются в формате XML.

DataSet представляет собой кэш данных, расположенный в оперативной памяти. DataSet состоит из коллекции объектов класса DataTable.

Доступ к ячейкам таблицы можно получить, используя свойства класса DataTable (Rows, Cols, Item) - но запись поля таблицы в файл может быть некорректной из-за того, что технология ADO.NET предусматривает кэширование данных.

Пример такого кода:

System::Data::DataRow ^ newRow = Table->NewRow();
Table->Rows->Add(newRow);

Поэтому следует пользоваться методами объекта DataSet.

 Скачать проект TableEditor1 в архиве .zip (13 Кб)

Пример 2. Пишем проект TableEditor2 для связанных таблиц.

Компонента DataGrid - решение для показа связанных таблиц в одной компоненте, в DataGridView такой возможности нет. Не все компоненты доступны по умолчанию, в том числе, и DataGrid. Щёлкаем правой кнопкой мыши на панели элементов управления, Выбрать элементы, на вкладке "Компоненты .NET Framework" устанавливаем флажок возле элемента DataGrid пространства имен System.Windows.Forms, нажимаем ОК.

После этого DataGrid можно добавить на форму.

Описаны глобально:

private: Boolean ShowClients; //Флажок-переключатель таблиц
private: System::Data::DataSet ^ DataSet1;

На загрузку формы (обработчик события Load):

ShowClients = true;
//Создадим таблицу:
System::Data::DataTable ^ Table = gcnew DataTable("Клиенты");
//Создадим и настроим столбец программно:
DataColumn ^ Column = gcnew DataColumn("Название организации");
Column->ReadOnly = true;
Column->Unique = true;
Table->Columns->Add(Column);
//Добавим столбцы с настройками по умолчанию, указав только названия:
Table->Columns->Add("Контактное лицо");
Table->Columns->Add("Телефон");
//Создадим DataSet и добавим туда таблицу:
DataSet1 = gcnew DataSet();
DataSet1->Tables->Add(Table);
//Добавим в таблицу предустановленные записи об организациях-заказчиках
Table->Rows->Add("НГАСУ", "Иванов Максим", "3234566");
Table->Rows->Add("НГТУ", "Сидорова Ксения", "3630313");
//Создадим вторую таблицу - "Заказы"
System::Data::DataTable ^ Table2 = gcnew DataTable("Заказы");
DataColumn ^ Column2 = gcnew DataColumn("Номер заказа");
Column2->DataType = System::Type::GetType("System.Int32");
Column2->AutoIncrement = true; //Автоматический счётчик заказов
Column2->ReadOnly = true; Column2->Unique = true; //Название организации - уникально!
Table2->Columns->Add(Column2);
Table2->Columns->Add("Объем заказа");
Table2->Columns->Add("Организация-заказчик");
//Добавим в DataSet вторую таблицу:
DataSet1->Tables->Add(Table2);
Table2->Rows->Add(1, "100000", "НГАСУ");
Table2->Rows->Add(2, "200000", "НГАСУ");
//Обеспечим отношение 1:N между первой и второй таблицами:
DataColumn ^ Parent = DataSet1->Tables["Клиенты"]->Columns["Название организации"];
DataColumn ^ Child = DataSet1->Tables["Заказы"]->Columns["Организация-заказчик"];
DataRelation ^ Link1 = gcnew DataRelation("Ссылка на заказы клиента", Parent, Child);
// В Parent значения в связываемом столбце должны быть уникальными, в Child - нет
DataSet1->Tables["Заказы"]->ParentRelations->Add(Link1);
dataGrid1->SetDataBinding(DataSet1, "Клиенты");
dataGrid1->CaptionText = "Родительская таблица \"Клиенты\"";
dataGrid1->CaptionFont = gcnew System::Drawing::Font("Consolas", 11);

На нажатие кнопки (переключает между родительской и дочерней таблицами):

if (ShowClients == true) {
 dataGrid1->SetDataBinding(DataSet1, "Клиенты");
 dataGrid1->CaptionText = "Родительская таблица \"Клиенты\"";
}
else {
 dataGrid1->SetDataBinding(DataSet1, "Заказы");
 dataGrid1->CaptionText = "Дочерняя таблица \"Заказы\"";
}
ShowClients = !ShowClients;

 Скачать проект TableEditor2 в архиве .zip (14 Кб)

Пример 3. Делаем всё по-современному - через DataGridView. Подробнее об этом компоненте.

Он представляет собой прямоугольный массив ячеек, который можно рассматривать как коллекцию строк или столбцов.

Rows - коллекция строк, имеет тип DataGridRowCollection

Columns - коллекция столбцов, тип DataGridColumnCollection

Оба свойства индексируются как массивы для доступа к конкретной строке/столбцу, нумерация с нуля.

Cells - коллекция ячеек из объекта DataGridRowCollection, приведём пример доступа к ячейке:

try {
 MessageBox::Show(dataGridView1->Rows[1]->Cells[1]->Value->ToString());
} 
catch (...) { MessageBox::Show("Нет такой ячейки"); }

RowCount, ColumnCount - количество строк и столбцов

В несвязанном режиме компонент может отображать любые табличные данные.

Методы для добавления/удаления/редактирования строк относятся к коллекции Rows и имеют типовые имена: Add, Insert, Clear, AddCopy, InsertCopy, Remove, RemoveAt и могут иметь по несколько перегрузок каждая, например, для Add есть версии Add(), Add(КоличествоНовыхСтрок), Add (DataGridViewRow ^row), Add (... Object ^object)

Настройка внешнего вида компонента также типовая: такие свойства, как BackColor, Alignment, Font и т.д. находятся в объекте типа DataGridViewCellStyle

Каждая ячейка представлена объектом System::Windows::Forms::DataViewCell, за "личный" внешний вид ячейки отвечает свойство InheritedStyle, вид по умолчанию - DefaultCellStyle

Примеры.

1. По нажатию кнопки перекрасим фон таблицы в розовый цвет:

dataGridView1->DefaultCellStyle->BackColor=Color::Pink;

2. ...или только фон выбранной ячейки:

if (cell_y>-1 && cell_x>-1)
 dataGridView1->Rows[cell_y]->Cells[cell_x]->Style->BackColor=Color::Green;

Значения cell_y, cell_x описаны глобально в классе формы:

private: int cell_y,cell_x;

инициализируются в обработчике её события Load:

cell_y = cell_x = -1;

и получаются значения в обработчиках событий dataGridView1_KeyUp, dataGridView1_MouseUp (одинаковым кодом):

cell_y = dataGridView1->CurrentCell->RowIndex;
cell_x = dataGridView1->CurrentCell->ColumnIndex;

3. Обработчик события dataGridView1_CellFormatting для выделения текущей ячейки жёлтым фоном:

e->CellStyle->SelectionBackColor = Color::Yellow;
e->CellStyle->SelectionForeColor = Color::Black;

4. Сделаем в dataGridView1 таблицу со значениями функции. Код по нажатию кнопки:

dataGridView1->Columns->Clear();
dataGridView1->ColumnCount=2;
dataGridView1->Rows->Add (10); //Добавили 10 строк
dataGridView1->Columns[0]->Name = "X";
dataGridView1->Columns[1]->Name = "Y(X)";
float x; int i;
for (x=1.5,i=0; i<10; x+=0.1,i++) {
 dataGridView1->Rows[i]->Cells[0]->Value = Convert::ToString (x);
 dataGridView1->Rows[i]->Cells[1]->Value = Math::Round(x*x, 2).ToString(); 
 //или dataGridView1->Rows[i]->Cells[1]->Value = (x*x).ToString("f");
}

5. Есть также множество событий, связанных с редактированием ячейки: CellBeginEdit, CellEndEdit, CellParsing, CellValidating, CellValidated и т.д.

Например, по умолчанию наша таблица редактируется. Чтобы разрешить в первом столбце (Y(X)) ввод только числовых значений, напишем следующий код, выполняемый по событию CellValueChanged:

String ^Val = 
 dataGridView1->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value->ToString();
if (e->ColumnIndex==1) {
 float val;
 bool A = Single::TryParse(Val,
  System::Globalization::NumberStyles::Number,
  System::Globalization::NumberFormatInfo::CurrentInfo, val);
  if (A==false) {
   dataGridView1->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value = lastValue;
   MessageBox::Show("Неверное число "+val.ToString(),"Ошибка");
  }
}

Величина lastValue описана в классе формы:

private: float lastValue;

и, по событию CellBeginEdit, сохраняет предыдущее значение, хранимое в ячейке:

if (e->ColumnIndex==1) lastValue = 
 Convert::ToDouble(dataGridView1->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value);

 Скачать проект TableEditor3 в архиве .zip (14 Кб)

16.03.2015, 15:33 [23396 просмотров]


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

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