Datagrid что это
Перейти к содержимому

Datagrid что это

  • автор:

DataGrid

Элемент DataGrid очень похож своим внешним видом на ListView, при использовании GridView, но при этом несет в себе больший функционал. Например, DataGrid может автоматически генерировать столбцы, в зависимости от вводимых Вами данных. Tакже, DataGrid по умолчанию можно редактировать, благодаря этому конечный пользователь будет в состоянии изменять данные в ячейках DataGrid.

Чаще всего DataGrid используется в сочетании с базой данных, но, как и большинство WPF элементов, может функционировать и на локальном источнике данных, например, на списке объектов. Продемонстрировать это очень просто (именно такой подход к обучению мы предлагаем Вам в рамках руководства).

Простой элемент DataGrid

Начать можно вовсе без каких-либо свойств DataGrid, ведь он и так, «из коробки» предлагает большой функционал. Именно так мы и сделаем в примере ниже, подключив к DataGrid список объектов User, в качестве источника данных:

xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
Title=»SimpleDataGridSample» Height=»180″ Width=»300″>

using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.DataGrid_control
public partial class SimpleDataGridSample : Window
public SimpleDataGridSample()
InitializeComponent();

List users = new List();
users.Add(new User() < Name = "John Doe", Birthday = new DateTime(1971, 7, 23) >);
users.Add(new User() < Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) >);
users.Add(new User() < Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) >);

dgSimple.ItemsSource = users;
>
>

public class User
public int Id < get; set; >

public string Name < get; set; >

public DateTime Birthday < get; set; >
>
>

Фактически, это все, что Вам необходимо знать, для того чтобы начать использование DataGrid. Источником данных может быть таблица/представление базы данных или даже файл XML — в этом плане DataGrid способен разобраться со всем.

Нажав на одну из ячеек, Вы заметите, что в DataGrid есть поддержка редактирования свойств по умолчанию. Приятным бонусом является тот факт, что если вы кликните на заголовок любого столбца, то заметите, что DataGrid поддерживает еще и сортировку.

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

В итоге

Наверняка Вы обратили внимание на то, насколько просто начать работу с DataGrid, но, при этом, он является очень гибким в плане настройки элементом. В следующих главах мы погрузимся во множество интересных механизмов, которые можно реализовать с помощью этого элемента, так что продолжайте читать.

This article has been fully translated into the following languages:

Is your preferred language not on the list? Click here to help us translate this article into your language!

Используем DataGrid в WPF

Не так давно мне потребовалось использовать таблицу в приложении на C#. По наивности я подумал, что буду использовать всё самое свежее и выбрал для проекта WPF вместо WinForm и, конечно, взял самый свежий .net framework 4.5. Тут-то и начались проблемы. Как всегда, я решил, что в Яндексе найдётся всё, но не тут то было — в интернете (вернее в РУнете) вообще ничего о DataGrid нет. Постоянно, как бы хитро не изменял запросы, я попадал на DataGridView из WinForm. Самое интересное в том, что платформа WPF полностью переработана и многое из того, что работало в WinForm в WPF не работает вообще никак.

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

После продолжительного негодования я открыл большую и толстую книгу по WPF. И вот, чудо! Там было всё, как изменить размер, переименовать и перекрасить что угодно и как угодно, но о том, как элементарно достать запись из DataGrid не было и слова.

Отчаявшись, я решил было перейти на WinForm, но вспомнив старую добрую пословицу «если программа не работает, то проблема не в коде, а в программисте», решил разобраться в проблеме и (правда не помню на каком сайте) нашёл решение (это был сайт на английском языке в самых чёрных глубинах интернета). Название сайта вспомнил, ссылка в конце документа.

Привожу пример, как положить и достать информацию из DataGrid в WPF:

Для начала создадим новое приложение и в главном окне разместим элемент DataGrid, назовём его grid.
Далее создадим класс, который будет хранить информацию для таблицы:

 class MyTable < public MyTable(int Id, string Vocalist, string Album, int Year) < this.Id = Id; this.Vocalist = Vocalist; this.Album = Album; this.Year = Year; >public int Id < get; set; >public string Vocalist < get; set; >public string Album < get; set; >public int Year < get; set; >> 

После этого заполним таблицу с помощью события Loaded:

//Добавим информацию в таблицу private void grid_Loaded(object sender, RoutedEventArgs e) < Listresult = new List(3); result.Add(new MyTable(1, "Майкл Джексон", "Thriller", 1982)); result.Add(new MyTable(2, "AC/DC", "Back in Black", 1980)); result.Add(new MyTable(3, "Bee Gees", "Saturday Night Fever", 1977)); result.Add(new MyTable(4, "Pink Floyd", "The Dark Side of the Moon", 1973)); grid.ItemsSource = result; > 

После всего получим информацию о строчке по событию MouseUp (клик мышкой):

 //Получаем данные из таблицы private void grid_MouseUp(object sender, MouseButtonEventArgs e)

Заключение

Обратите внимание, что обращаться к элементам таблицы в WPF действительно легче, чем в WinForm (напомню, что в WinForm нужно обязательно указывать номер столбца и ячейки), более того, таблица сохраняет исходный тип данных и это очень удобно при их обработке.

Скриншот того, что получилось:

Полный исходный XAML код приложения (одна из вкусняшек WPF, можно посмотреть тип элемнта, его имя и подисанные на него события, а также прочую информацию):

Полный исходный код на языке C#:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DataGrid < /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >//Загрузка содержимого таблицы private void grid_Loaded(object sender, RoutedEventArgs e) < Listresult = new List(3); result.Add(new MyTable(1, "Майкл Джексон", "Thriller", 1982)); result.Add(new MyTable(2, "AC/DC", "Back in Black", 1980)); result.Add(new MyTable(3, "Bee Gees", "Saturday Night Fever", 1977)); result.Add(new MyTable(4, "Pink Floyd", "The Dark Side of the Moon", 1973)); grid.ItemsSource = result; > //Получаем данные из таблицы private void grid_MouseUp(object sender, MouseButtonEventArgs e) < MyTable path = grid.SelectedItem as MyTable; MessageBox.Show(" ID: " + path.Id + "\n Исполнитель: " + path.Vocalist + "\n Альбом: " + path.Album + "\n Год: " + path.Year); >> class MyTable < public MyTable(int Id, string Vocalist, string Album, int Year) < this.Id = Id; this.Vocalist = Vocalist; this.Album = Album; this.Year = Year; >public int Id < get; set; >public string Vocalist < get; set; >public string Album < get; set; >public int Year < get; set; >> > 

Для примера использован Visual Studio 2012 и .net 4.0.

P.S. Не знаю, может, я рассказал очевидную для кого-то вещь, однако на это потратил довольно много времени, поэтому и решил поделиться.

DataGridView в паре с DataTable

Приложение редактирования SQL таблиц

Приложение взаимодействия элемента визуального отображения таблиц DataGridView и связанного источника данных типа DataTable. Приложение позволяет работать с выбранной таблицей SQL базы данных, осуществлять создание и удаление строк, редактирование ячеек с записью в базу данных.

Термин связанный источник подразумевает, что изменения значений ячеек, добавление и удаление строк элемента DataGridView синхронно передаётся объекту DataTable. И наоборот, изменения в связанном DataTable тут же отображаются в таблице DataGridView.

  • — dgvDatabase для отображения списка таблиц базы данных;
  • — dgvTable для редактирования выбранной таблицы базы.

База данных в составе приложения

Исследуемая база данных содержит 3 различных таблицы. Для расширенного эксперимента в таблицах создано многообразие типов данных: int, float, bit, nvarchar, date. Столбцы имеют различные свойства инициализации: NULL, NOT NULL и значения по умолчанию.

Файл базы данных прикреплен к исходнику приложения. Подключение базы данных к SQL серверу можно осуществить с помощью среды программирования Visual Studio, как подключиться подробно описано на странице создание, подключение и отсоединение баз данных в Visual Studio. Подключить базу так же можно и в среде администрирования баз данных SQL Server Management Studio.

Инициализация приложения

Инициализация приложения и интерфейс обращения к базе данных практически аналогичен описанному в статье DataGridView — просмотр баз данных LocalDB. Во время инициализации приложения происходит получение списка таблиц базы с помощью представления информационной схемы INFORMATION_SCHEMA.TABLES . После запроса метаданные возвращаются в виде строк для каждой отдельной таблицы базы и отображаются в элементе dgvDatabase.

В списке таблиц ключевым является столбец с названием TABLE_NAME . При выборе пользователем любой ячейки элемента dgvDatabase считывается название таблицы из строки и данные загружаются в элемент DataGridView dgvTable для последующего редактирования. Программный код инициализации заключен в оболочку метода Init(), который вызывается в конструкторе формы.

private void Init()

Создание новой строки

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

В прикрепленном приложении новая строка вставляется в базу данных после редактирования любой ячейки и перевода фокуса на другие строки. При редактировании ячейки новая строка появляется в связанном источнике данных, в нашем случае в объекте DataTable. В событии DataGridView.RowValidated, возникающем при потере фокуса можно отследить создание новой строки посредством свойства DataRowState.Added связанного источника. Если проверка истинна, то значения строки записываются в базу данных. Для валидации заполнения новой строки предназначено событие DataGridView.RowValidating.

Вставка значений новой строки в событии DataGridView.RowValidated, возникающим после окончания валидации:

private void DgvTable_RowValidated(object sender, DataGridViewCellEventArgs e) < DataTable dtSource = (DataTable)dgvTable.DataSource; foreach (DataRow row in dtSource.Rows) < if (row.RowState == DataRowState.Added) < Insert(dtSource, row); >> > 

Получение значений по умолчанию

При создании новой строки требуются значения по умолчанию, и очень желательна их идентичность значениям в базе данных. Хотя DataColumn в составе DataTable имеет свойство DataColumn.DefaultValue, оно не заполняется при SQL запросах. Запросить из базы данных реальные значения по умолчанию столбцов не получится. Это связано с тем, что значения по умолчанию могут содержать не только величины, но и инициализирующие функции, например: GetDate(), NEW_ID(), которые определяют значения столбцов непосредственно во время вставки строки. Если запросить значения по умолчанию с помощью схемы INFORMATION_SCHEMA.COLUMNS , то результат вернется в виде строк вида «getdate()» , «new_id()» , «((0))» , («2022-01-20») и так далее.

Но получить значения столбцов по умолчанию все же можно. Необходимую процедуру можно осуществить различными способами:
— создать полную пустую временную копию таблицы, вставить в нее строку, считать значения, удалить таблицу.
— вставка строки в текущую таблицу во время транзакции, после считывания значений, откат транзакции.
Каждый из способов имеет свои достоинства и недоставки, но оба они позволяют получать реальные значения по умолчанию для столбцов с помощью самого механизма базы данных.

Для описываемого приложения написан метод GetDefaultValues(. ) получения значений по умолчанию путем фиктивной вставки строки. Полученные default значения присваиваются соответствующим столбцам связанного источника данных DataTable. Ввод данных по умолчанию непосредственно в связанный источник освобождает от необходимости повторяющейся обработки события DefaultValuesNeeded.

Получение и присваивание default значений происходит в событии смены источника данных:

private void dgvTable_DataSourceChanged(object sender, EventArgs e)
  1. Запрос схемы столбцов текущей таблицы и получение свойств столбцов парно COLUMN_NAME-COLUMN_DEFAULT , исключая столбец первичного идентификатора;
  2. Фиктивная вставка строки в базу с пустыми значениями (не являющимися NULL) столбцов, исключая столбцы, у которых обнаружено значение по умолчанию;
  3. Полученные default значения последней вставленной строки присваиваются одноименным столбцам связанного источника.

После вышеописанной процедуры, при вставке новой строки в DataGridView, в соответствующих столбцах появляются значения по умолчанию идентичные предусмотренным в базе данных.
К сведению. Откат транзакции не возвращает назад значение IDENTITY (AUTO_INCREMENT) первичного ключа. Это прерогатива исключительно движка базы данных.

Программный код получения значений по умолчанию из базы данных:

public void GetDefaultValues(DataTable dtSource) < // Запрос информации о значениях по умолчанию. string sq = "SELECT COLUMN_NAME, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + dtSource.TableName + "' AND COLUMNPROPERTY(object_id('" + dtSource.TableName + "'), COLUMN_NAME, 'IsIdentity')=0;"; DataTable dtSchema = ConnectDB.SqlQuery(sq); int count = 0; Listparameters = new(); List listnames = new(); List listvalues = new(); foreach (DataRow r in dtSchema.Rows) < if (r["COLUMN_DEFAULT"] == DBNull.Value) < listnames.Add("[" + r["COLUMN_NAME"] + "]"); SqlParameter parUri = new() < // Конвертирует в необходимый тип автоматически, // без явного указания типа. // DbType = ConvertToDBType.Convert(dataTable.Columns[colindex].DataType), Direction = ParameterDirection.Input, ParameterName = "Param" + count, // Вставка пустого значения, // разрешено вставлять даже если столбец NOT NULL. Value = "" >; parameters.Add(parUri); listvalues.Add("@" + parUri.ParameterName); count++; > > string names = string.Join(',', listnames); string values = string.Join(',', listvalues); // ===== // Алгоритм 1 // Создать транзакцию // Вставить строку в таблицу // Прочитать значения по умолчанию // Откатить транзакцию. string sqlquery = "BEGIN TRANSACTION;"; sqlquery += "INSERT INTO " + dtSource.TableName + " (" + names + ") VALUES(" + values + ");"; string lastid = "SELECT IDENT_CURRENT('" + dtSource.TableName + "')"; sqlquery += "SELECT * FROM " + dtSource.TableName + " WHERE + lastid + ");"; sqlquery += "ROLLBACK;"; DataTable tableDefault = ConnectDB.SqlQuery(sqlquery, parameters); // Добавляем данные по умолчанию непосредственно в связанный источник данных. foreach (DataRow r in dtSchema.Rows) < foreach (DataColumn col in dtSource.Columns) < if ((string)r["COLUMN_NAME"] == col.ColumnName && r["COLUMN_DEFAULT"] != DBNull.Value) < object o = tableDefault.Rows[0][col.ColumnName]; col.DefaultValue = o; >> > > 

Редактирование ячеек DataGridView

В загруженных строках dgvTable можно редактировать любую ячейку, кроме идентификатора. В приложении отслеживаются только изменения значений ячеек, далее отредактированное значение записывается в базу данных при потере фокуса ячейкой или после нажатия клавиши Enter.

Изменение значений своих ячеек элемент DataGridView сопровождает событием CellValueChanged. Редактируются ячейки, только существующие в базе, новые ячейки добавляются в базу данных во время вставки новой строки.

private void DgvTable_CellValueChanged(object sender, DataGridViewCellEventArgs e) < DataTable dtSource = (DataTable)dgvTable.DataSource; // Обновляется запись в базе данных только после изменения. // Редактируется ячейка строки, которая присутствует в связанном источнике DataTable, т.е. // данная запись уже есть в базе данных. // Новые значения вставляются после валидации новой строки. if (dtSource.Rows.Count - 1 >= e.RowIndex && dtSource.Rows[e.RowIndex].RowState == DataRowState.Unchanged) < Update(dtSource, e.RowIndex, e.ColumnIndex); >> 

Валидация вводимых значений

Движок DataGridView имеет встроенную функциональность проверки соответствия типа вводимого значения типу ячейки. При связанном источнике данных ячейки наследуют типы соответствующих столбцов DataTable.

Валидация введенного в ячейку значения происходит в событии DataGridView.CellValidating при потере фокуса ячейкой. В данном событии может находиться программный код оповещения пользователя о недопустимости ввода текущего значения. Если проигнорировать некорректность в этом событии, возникнет событие DataGridView.DataError, которое вернет первоначальное корректное значение.

Сочетание этих двух событий с диалоговыми окнами позволяют создать визуальную логику исправления ошибочного ввода. После успешной валидации значение ячейки можно записать в SQL базу данных.

Программный алгоритм валидации вводимых значений с диалоговым оповещением пользователя:

private void DgvTable_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) < // Не очень удобно валидировать новую строку. if (dgvTable.Rows[e.RowIndex].IsNewRow == true) < return; >DataTable dtSource = (DataTable)dgvTable.DataSource; // Получаем тип значений редактируемого столбца. Type type = dtSource.Columns[e.ColumnIndex].DataType; // Непосредственно валидация введенного значения. string? error = e.FormattedValue.ToString() switch < < Length: 0 >when dtSource.Columns[e.ColumnIndex].AllowDBNull == false => "Ячейка не может быть пустой!", < Length: >0 > when TryConvert(e.FormattedValue, type) == false => "Ячейка для значения " + type.Name + "!", _ => null >; // Если обнаружена некорректность ввода, оповещаем // пользователя диалоговым окном. if (error != null) < string action = " Выйти - Да Продолжить редактирование - Нет"; // Дополнительно выводим ошибку в текстовой метке. string errormsg = "Ошибка! Строка " + (e.RowIndex + 1) + ", столбец " + (e.ColumnIndex + 1) + ": " + error; dgvTable.Rows[e.RowIndex].ErrorText = errormsg; labelErrorMsg.Text = errormsg; // Если пользователь решил продолжить редактирование остаемся в ячейке. if (MessageBox.Show(error + " " + action, "Некорректные данные!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) < e.Cancel = true; >else < // Если пользователь отменил ввод. // Отменяем оповещения об ошибках. dgvTable.Rows[e.RowIndex].ErrorText = ""; labelErrorMsg.Text = ""; // Отменяем все некорректные изменения, возврат к предыдущим значениям. dgvTable.CancelEdit(); >> > 

Определение типа вводимого значения

Вводимое в ячейку значение отслеживается в событии CellValidating(object sender, DataGridViewCellValidatingEventArgs e) , где свойство e.FormattedValue содержит введенное пользователем значение. e.FormattedValue имеет тип object и поэтому неизвестен конкретный тип введенного значения. Например, e.FormattedValue содержит 5544 и нет сведений строка это или число. Проверка заключается в попытке конвертировать значение пользователя в тип, который должен содержать столбец.

Тип значения ячейки получаем из свойств столбцов связанного источника данных DataTable. Проверку соответствия типа производит метод приложения TryConvert(. ) . При успешной конвертации метод возвращает true, в противном случае false.

Программный код попытки конвертирования в заказанный тип. Применение метода показано в валидация вводимых значений.

public static bool TryConvert(object unknown, Type type) < try < object d = Convert.ChangeType(unknown, type); >catch (System.FormatException) < return false; >return true; > 

Удаление строк

В приложении можно удалять одну и более выделенных строк элемента dgvTable. Для процедуры удаления используется событие DataGridView.KeyDown с отслеживанием нажатия клавиши DELETE. Используя идентификаторы строк, осуществляется SQL запрос удаления выбранных записей.

Перед удалением открывается диалоговое окно, где запрашивается подтверждение либо отмена пользователем данного действия.

private void DgvTable_KeyDown(object sender, KeyEventArgs e) < if (e.KeyCode == Keys.Delete) < int numberrowsdelete = dgvTable.SelectedRows.Count; DataTable dt = (DataTable)dgvTable.DataSource; if (MessageBox.Show( "Удалить строки? Количество - " + numberrowsdelete, "Удаление строк!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) < string? queryString = null; foreach (DataGridViewRow row in dgvTable.SelectedRows) < queryString += "DELETE FROM " + dt.TableName + " WHERE Id"].Value.ToString() + ";"; >if (queryString != null) ConnectDB.SqlQuery(queryString); > > > 

Метод вставки новой строки в базу данных

При визуальной вставке новой строки в элемент DataGridView автоматически создается новая строка в связанном источнике DataTable, но реально в базу данных ничего не записывается. Для вставки новой строки непосредственно в базу данных требуется дополнительный программный код.

В приложении за запись новых строк отвечает метод главной формы Insert(DataTable dtSource, DataRow row) , который в качестве параметра получает новую строку. Данные новой строки записываются в SQL базу данных.

Программный код метода вставки строки в базу и синхронизации идентификаторов:

void Insert(DataTable dtSource, DataRow row) < Listparameters = new(); List listnames = new(); List listvalues = new(); // Формирование имен и значений столбцов. int count = 0; foreach (DataColumn col in row.Table.Columns) < // данные вставляем в столбцы, кроме первичного идентификатора. if (col.AutoIncrement == false) < listnames.Add("[" + col.ColumnName + "]"); SqlParameter parUri = new() < // Конвертирует в необходимый тип автоматически, // без явного указания типа. //DbType = ConvertToDBType.Convert(dataTable.Columns[colindex].DataType), Direction = ParameterDirection.Input, ParameterName = "Param" + count, Value = row[col.ColumnName] >; parameters.Add(parUri); count++; listvalues.Add("@" + parUri.ParameterName); > > string names = string.Join(',', listnames); string values = string.Join(',', listvalues); // Фиксируем все добавления строк в источник данных DataTable. row.AcceptChanges(); // SQL запрос на вставку, одновременно запрос на последний номер идентификатора для синхронизации Id. // Иначе видимые в DataGridView идентификаторы могут не совпадать с идентификаторами записей в базе. string querystring = "INSERT INTO " + row.Table.TableName + " (" + names + ") VALUES(" + values + ");"; querystring += "SELECT IDENT_CURRENT('" + row.Table.TableName + "');"; DataTable lastId = ConnectDB.SqlQuery(querystring, parameters); // Синхронизируем первичные идентификаторы в базе данных и в DataGridView. // Это гарантирует совпадение идентификаторов в виртуальной таблице // с первоисточником в базе данных. // Записываем настоящий идентификатор строки, // полученный из базы данных. dtSource.Columns["Id"]!.ReadOnly = false; row["Id"] = lastId.Rows[0][0]; dtSource.Columns["Id"]!.ReadOnly = true; > 

Синхронизация первичных ключей базы данных и DataGridView

В случае с автоматическим приращением (IDENTITY (AUTO_INCREMENT)), при вставке новых строк не обеспечивается идентичность первичных идентификаторов записей базы данных и строк элемента управления DataGridView, что может вызвать нежелательные последствия.

При создании новой строки, в событии dgvTable.RowEnter, ячейке идентификатора элемента dgvTable временно присваивается значение -1. Метод Insert(DataTable dtSource, DataRow row) написан так, что одновременно со вставкой строки запрашивается последний вставленный идентификатор. Далее данный идентификатор присваивается ячейке идентификатора новой строки связанного источника, таким образом обеспечивается идентичность первичных ключей.

Программный код выделения новой строки отличающимся цветом и временным идентификатором:

private void DgvTable_RowEnter(object sender, DataGridViewCellEventArgs e) < if (dgvTable.Rows[e.RowIndex].IsNewRow == true) < // При фокусе на новой строке выделяем ее цветом. dgvTable.Rows[e.RowIndex].DefaultCellStyle.BackColor = newRowColor; // Первоначально идентификатор неизвестен для новой строки, // после успешной вставки строки получаем идентификатор из базы. // Если данный код удалить, то при многократном фокусировании и покидании // фокуса новой строкой не на новую строку автоинкремент DataGridView увеличивает // значение идентификатора и не сбрасывает его при возврате фокуса. // В базе же данных свой отсчет автоинкремента не связанный с DataGridView. dgvTable.Rows[e.RowIndex].Cells["Id"].Value = "-1"; >> 

Программный код синхронизации первичных ключей, полный код метода вставка новой строки:

void Insert(DataTable dtSource, DataRow row) < . // SQL запросы на вставку и на последний номер идентификатора для синхронизации Id. // Иначе видимые в DataGridView идентификаторы могут не совпадать с идентификаторами в базе. string querystring = "INSERT INTO " + row.Table.TableName + " (" + names + ") VALUES(" + values + ");"; querystring += "SELECT IDENT_CURRENT('" + row.Table.TableName + "');"; DataTable lastId = ConnectDB.SqlQuery(querystring, parameters); // Синхронизируем первичные идентификаторы в базе данных и источнике данных DataTable. // Это гарантирует совпадение идентификаторов в DataGridView // с первоисточником в базе данных. // Записываем настоящий идентификатор строки, // полученный из базы данных. dtSource.Columns["Id"]!.ReadOnly = false; row["Id"] = lastId.Rows[0][0]; dtSource.Columns["Id"]!.ReadOnly = true; >

Вместо заключения

В данной статье описана работа в паре элемента DataGridView и объекта DataTable в качестве источника данных. Практический пример прикреплен к странице. DataTable предоставляет простой и удобный интерфейс для работы с таблицами баз данных.

Функциональность DataTable в паре с элементом управления DataGridView можно применять для редактирования таблиц источников данных. Простота работы с классом DataTable позволяет писать приложения обработки данных в кратчайшие сроки.

Скачать исходник

Тема: «DataGridView в паре с DataTable»

Datagrid что это

Автор: Dimon aka Manowar
Опубликовано: 17.03.2002
Уровень: Учебник
Проголосовало 20 читателей.
Средняя оценка 3,90.

В элемент управления DataGrid (как впрочем и в DataList) встроена мощная поддержка возможности редактирования связанных с этим элементом данных. Оба этих элемента управления позволяют управлять отображением выбранной или редактируемой записи, а также обновлять связанные данные. И все это при минимальном программировании. Например, для того, чтобы установить в режим редактирования пятую строку DataGrid необходимо присвоить свойству EditItemIndex элемента управления DataGrid значение 4 (нумерация строк в DataGrid начинается с 0). Соответственно для того, чтобы выйти из режима редактирования необходимо свойству EditItemIndex присвоить значение -1. Наиболее сложной операцией при редактировании DataGrid является извлечение введенных данных и запись их в источник данных, но эта операция сложна только по сравнению с прочими простейшими операциями редактирования. Впрочем вскоре мы в этом убедимся.

Для генерации событий редактирования, отмены редактирования и сохранения редактирования (EditCommand, CancelCommand и UpdateCommand соответственно) в DataGrid предусмотрен специальный тип столбца � ButtonColumn. Он генерит кнопки редактирования, сохранения и отмены редактирования, нажатие которых вызsdftn соответствующие события в DataGrid. Вооружившись этими данными попробуем создать простейший DataGrid с возможностью редактирования. Создадим DataGrid с автоматической генерацией столбцов и добавим к нему столбец типа ButtonColumn.

<%@ Page language="c#" Src="DataGridEdit1.aspx.cs" %>


DataGridEdit1









Теперь необходимо связать DataGrid с данными из источника данных (в данном случае это будут данные из таблицы Authors базы pubs) и обработать события редактирования для DataGrid.

Для связывания данных применяется следующий метод:

private void bindData()
SqlConnection myConn = new SqlConnection(«server=localhost;uid=sa;pwd=;database=pubs»);
SqlDataAdapter myData = new SqlDataAdapter(«select au_id, au_fname, au_lname, state, contract from authors», myConn);
DataSet ds = new DataSet();
myData.Fill(ds);
DataGrid1.DataSource = ds.Tables[0].DefaultView;
DataGrid1.DataKeyField = «au_id»;
DataGrid1.DataBind();
>

Этот метод получает данные из источника данных и связывает их с элементом DataGrid. Кроме этого устанавливается значение свойства DataKeyField (нужно же будет как-то искать потом редактируемую строку в наборе данных). Обработчики событий редактирования и отмены редактирования просты до невозможности. Все, что в них происходит, это устанавливается значение свойства EditItemIndex элемента DataGrid и вызывается метод bindData():

private void DataGrid1_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
DataGrid1.EditItemIndex = e.Item.ItemIndex;
bindData();
>
private void DataGrid1_CancelCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
DataGrid1.EditItemIndex = -1;
bindData();
>

Наиболее сложным (и интересным) является метод � обработчик события сохранения данных. Перед тем, как представить его код, рассмотрим как DataGrid создает элементы при связывании данных.

В момент связывания данных в BoundColumn (а именно эти столбцы применяются при установке AutoGeneratedColumn=�true� для DataGrid) в ячейку генерируемой таблицы для каждого поля вставляется либо LiteralControl с данными из соответствующего поля источника данных, либо же (только для редактируемой строки) элемент TextBox, значению свойства Text которого присваивается значение данных из соответствующего поля. Исходя из вышесказанного данные, которые необходимо сохранить, находятся в элементах TextBox, которые в свою очередь являются первыми (и единственными) элементами управления в соответствующих ячейках.

private void DataGrid1_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
SqlConnection myConn = new SqlConnection(«server=localhost;uid=sa;pwd=;database=pubs»);
SqlDataAdapter myData = new SqlDataAdapter(«select au_id, au_fname, au_lname, state, contract from authors», myConn);
DataSet ds = new DataSet();
myData.Fill(ds);
ds.Tables[0].PrimaryKey = new DataColumn[] ;
DataRow dr = ds.Tables[0].Rows.Find(DataGrid1.DataKeys[e.Item.ItemIndex]);
if(dr != null)
dr[«au_fname»] = ((TextBox)e.Item.Cells[2].Controls[0]).Text;
dr[«au_lname»] = ((TextBox)e.Item.Cells[3].Controls[0]).Text;
dr[«state»] = ((TextBox)e.Item.Cells[4].Controls[0]).Text;
dr[«contract»] = Boolean.Parse(((TextBox)e.Item.Cells[5].Controls[0]).Text);
>
ds.AcceptChanges();
DataGrid1.EditItemIndex = -1;
DataGrid1.DataSource = ds.Tables[0].DefaultView;
DataGrid1.DataKeyField = «au_id»;
DataGrid1.DataBind();
>

Как видите ничего экстраординарного в данном методе нет. Сначала метод ищет редактируемую строку. Затем в поля этой строки записываются введенные данные. И, наконец, изменения сохраняются и данные связываются с DataGrid.

В данном примере не происходит реального изменения данных в источнике данных � меняются только данные в DataSet. Но ничего не стоит изменить приведенный выше метод и добавить также код записи изменений в базу данных.

В приведенном выше примере при редактировании строки выводятся элементы управления TextBox для всех полей, в том числе и для поля au_id, представляющего собой первичный ключ таблицы authors. Данные полей с первичным ключом обычно не редактируются дабы не нарушить целостность данных. Поэтому хорошо было бы убрать возможность редактирования данных в поле au_id. Это сделать очень просто � установив свойство ReadOnly второго столбца DataGrid в true. К сожалению элемент управления DataGrid не предоставляет доступ к списку автоматически генерируемых столбцов, так что придется сначала также описать все столбцы в DataGrid и убрать AutoGeneratedColumns=true. Вот как будет выглядеть необходимое описание столбцов в DataGrid:

Остальной код предыдущего примера остается без изменений. Теперь при редактировании строки поле au_id недоступно для изменений.

Столбцы типа BoundColumn и их использование для отображения и редактирования данных в DataGrid очень простое и, вместе с тем, достаточно мощное средство. Но как быть если для редактирования данных в DataGrid необходимо использовать элементы управления, отличные от поля ввода (например выпадающий список или флажок)? В этом случае на помощь приходят столбцы шаблонов (TemplateColumn). Данный тип столбца DataGrid позволяет полностью управлять форматом отображения и редактирования данных � вы можете выводить данные в несколько строк или использовать для редактирования данных любые элементы управления. Но при редактировании данных, описанных с помощью TemplateColumn возникают свои тонкости. Их то мы сейчас и рассмотрим.

Рассмотрим все тот же пример с данными из таблицы authors базы pubs. Только теперь все столбцы в DataGrid описаны как TemplatedColumn:

Все редактируемые колонки в DataGrid теперь описаны как TemplateColumn. Также изменены элементы редактирования данных � теперь штат автора нужно выбирать из выпадающего списка, а контракт с автором устанавливается с помощью флажка. Также теперь все элементы редактирования данных проименованы.

Теперь необходимо также изменить обработчик события UpdateCommand, так как код предыдущих примеров теперь работать не будет. Изменению подлежит только часть кода, связанная с получением данных из элементов редактирования, остальной код остается неизменным:

dr[«au_fname»] = ((TextBox) e.Item.Cells[2].Controls[1]).Text;
dr[«au_lname»] = ((TextBox) e.Item.FindControl(«lname»)).Text;
dr[«state»] = ((DropDownList) e.Item.FindControl(«state»)).SelectedItem.Value;
dr[«contract»] = ((CheckBox) e.Item.FindControl(«contract»)).Checked;

В приведенном выше коде показаны 2 способа получения данных из элементов редактирования при использовании столбцов типа TemplateColumn. Первый тип � уже знакомый нам доступ к элементу редактирования через список Controls соответствующей ячейки. Обратите внимание, что индекс элемента в списке теперь уже не 0, а 1, т.е. элемент редактирования является вторым в списке элементов ячейки. Это происходит потому, что при отображении данных в TemplateColumn ASP.NET воспринимает весь текст, заключенный в теге как шаблон. И при этом обрабатывается также пространство до и после элемента редактирования (в нашем случае пробелы и переводы строк обрабатывается как LiteralContol).

Второй способ доступа к элементам редактирования заключается в использовании метода FindContol, который ищет элемент управления по имени. Так как все элементы редактирования в шаблонах примера имеют имена, то появилась возможность использовать этот способ.

Как видите возможность редактирования данных в элементе управления DataGrid дает очень многое. Используя ее вы можете быстро отображать данные из источников данных и иметь полнофункциональную возможность редактирования этих данных.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *