Данный пост написан по мотивам статьи с codeproject “ListView in-line editing”.
Суть вопроса в том, что иногда возникает необходимость править данные в ячейках элемента ListView, который настроен на табличное представление (свойство View выставлено в Details). Как вы знаете напрямую это сделать нельзя, потому что ячейки эти реализованы как Read Only.
Исходный код доступен на GitHub.
В этом случае нам поможет TextBox. Как использовать данную методику я покажу на примере. В нашем распоряжении будет таблица с двумя столбцами Address и Value. При этом редактируемой может быть только ячейка в столбце Value. Таблица реализована при помощи элемента ListView и называется lvTable.
Идея подхода следующая: на форму мы поместим TextBox элемент (tbCell), он будет подставляться на место ячейки, данные который мы ходим изменить. Изменение осуществляется двойным щелчком левой кнопки мыши по соответствующей ячейке, после этого информация из нее будет скопирована в tbCell, доступный для редактирования. Для сохранения данных нужно нажать Enter или убрать фокус с элемента.
Далее предлагаю описание реализации в виде последовательности действий. Исходный код проекта прилагается к статье.
Шаг 1
На форме располагаем все необходимые элементы: ListView, TextBox, и настраиваем их.
ListView
Свойство | Значение |
BorderStyle | None |
FullRowSelect | True |
Name | lvTable |
Dock | Fill |
View | Details |
Добавим два столбца (Address и Value) на ListView, для этого нужно щелкнуть по значению свойства Columns и в появившемся окне сделать необходимые правки.
TextBox
Свойство | Значение |
Name | tbCell |
Dock | Fill |
Форма будет выглядеть примерно так, как показано ниже.
Шаг 2
Добавим загрузку демо данных на форму, для этого создадим обработчик события Load для формы и назовем его Form1_Load. После этого добавим в него код, заполняющий таблицу данными.
private void Form1_Load(object sender, EventArgs e) { Random rnd = new Random(); for (int i = 0; i < 10; i++) { ListViewItem lvi = new ListViewItem(); lvi.Text = i.ToString(); lvi.SubItems.Add(rnd.Next(0, 100).ToString()); lvTable.Items.Add(lvi) } }
Добавим обработчики событий для наших элементов.
ListView
Событие | Значение |
MouseDoubleClick | lvTable_MouseDoubleClick |
TextBox
Событие | Значение |
Leave | tbCell_Leave |
KeyPress | tbCell_KeyPress |
Шаг 3
Добавим в обработчики событий код, который позволяет “редактировать” ячейки таблицы.
Создадим три глобальных переменных.
bool CancelEdit = false; ListViewItem.ListViewSubItem CurrentSubItem = default(ListViewItem.ListViewSubItem); ListViewItem CurrentItem = default(ListViewItem);
CancelEdit – переменная, являющаяся флагом, через который передается разрешение на изменение данных ячейки.
CurrentItem – текущая запись таблицы.
CurrentSubItem – поле редактируемой записи.
Заполним кодом обработчики событий.
private void lvTable_MouseDoubleClick(object sender, MouseEventArgs e) { // Get current item of ListView CurrentItem = lvTable.GetItemAt(e.X, e.Y); if (CurrentItem == null) return; // Get sub item of current item CurrentSubItem = CurrentItem.GetSubItemAt(e.X, e.Y); int SubItembIndex = CurrentItem.SubItems.IndexOf(CurrentSubItem); // Check that we try edit column "Value" switch (SubItembIndex) { case 1: break; default: return; } // Set params for TextBox, show it and set focus int lLeft = CurrentSubItem.Bounds.Left + 2; int lWidth = CurrentSubItem.Bounds.Width - 2; tbCell.SetBounds(lLeft + lvTable.Left, CurrentSubItem.Bounds.Top + lvTable.Top, lWidth, CurrentSubItem.Bounds.Height); tbCell.Text = CurrentSubItem.Text; tbCell.Show(); tbCell.Focus(); } private void tbCell_KeyPress(object sender, KeyPressEventArgs e) { switch (e.KeyChar) { // If you press Enter than copy data from TextBox to ListView cell case (char)Keys.Return: CancelEdit = false; e.Handled = true; tbCell.Hide(); break; // If you press Escape than data in ListView cell stay without changes case (char)Keys.Escape: CancelEdit = true; e.Handled = true; tbCell.Hide(); break; } } private void tbCell_Leave(object sender, EventArgs e) { tbCell.Hide(); if (CancelEdit == false) { CurrentSubItem.Text = tbCell.Text; } else { CancelEdit = false; } lvTable.Focus(); }
В своем проекте, на этом этапе, вам будет необходимо внести в обработчики событий свои коррективы: проверка вводимых данных и т.п.
На этом все, спасибо!