Как переключиться между DataGridViewTextBoxCell и DataGridViewComboBoxCell?
Вопрос
Я хочу иметь DataGridView с двумя столбцами.Первый столбец всегда будет иметь тип DataGridViewComboBoxColumn.На основе выбора в этом столбце я хотел бы иметь возможность изменить соответствующую ячейку во втором столбце либо на DataGridViewComboBoxCell, либо на DataGridViewTextBoxCell.
Я думаю надо просто сделать второй столбец типа DataGridViewColumn, но не понимаю механику изменения типа ячейки на лету.
Я работаю с VB.NET в Visual Studio 2005.
Заранее спасибо!
Обновлять: Я полагаю, что один из способов обойти это - сделать второй столбец DataGridViewComboBoxColumn и изменить атрибуты ячейки так, чтобы она вела себя либо как раскрывающийся список, либо как (редактируемый) раскрывающийся список без элементов.Последнее выглядит достаточно похоже на текстовое поле, и я мог бы с ним жить, и это не потребует изменения типа ячейки.
Решение
У меня нет версии VB.Net, но, надеюсь, этот небольшой фрагмент C# поможет вам или направит вас в правильном направлении.
В этом примере я создал простой DataGridView с двумя столбцами.Первым из них является DataGridViewComboBox, заполненный двумя вариантами:«Текст» или «Комбо».
В конструкторе для второго столбца изначально установлено значение DataGridViewTextBoxColumn.
Я обрабатываю событие CurrentCellDirtyStateChanged в DataGridView.Я проверяю, не загрязнена ли ячейка, и проверяю только первый столбец (ComboBox).Вам нужно вызвать CommitEdit, чтобы получить новое значение в комбинации, иначе вы будете смотреть на предыдущее значение.На основе выбора в поле со списком я затем перезаписываю ячейку во втором столбце новой ячейкой этого типа.
Вы должны добавить свою собственную логику (заполнить раскрывающиеся списки и обработать значение).Возможно, вы захотите сохранить значение, а затем поместить его обратно в ячейку или что-то еще.
Вот код, который я использовал и провел быстрый и грязный тест:
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty == false)
{
return;
}
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
if (dataGridView1.CurrentCell.ColumnIndex == 0)
{
if (((string)dataGridView1.CurrentCell.Value) == "Text")
{
dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[1] = new DataGridViewTextBoxCell();
}
else if (((string)dataGridView1.CurrentCell.Value) == "Combo")
{
dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Cells[1] = new DataGridViewComboBoxCell();
}
}
}
Вот быстрый перевод VB, который я протестировал и который работает.
Public Class Form1
Private Sub DataGridView1_CurrentCellDirtyStateChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
If DataGridView1.IsCurrentCellDirty = False Then
Return
End If
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
If DataGridView1.CurrentCell.ColumnIndex = 0 Then
If CStr(DataGridView1.CurrentCell.Value) = "Text" Then
DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(1) = New DataGridViewTextBoxCell
ElseIf CStr(DataGridView1.CurrentCell.Value) = "Combo" Then
DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(1) = New DataGridViewComboBoxCell
End If
End If
End Sub
Конечный класс
Вы потеряете любое значение, хранящееся в этом столбце, поэтому сначала вам необходимо его сохранить.
Джон
Другие советы
Вы можете создать собственный шаблон ячейки, в котором будет размещаться пользовательский элемент управления.В пользовательском элементе управления вы добавляете текстовое поле и поле со списком, а также добавляете метод/свойство, чтобы показать одно и скрыть другое.
Этот образец создает ячейку переключателя, нетрудно изменить код для размещения пользовательского элемента управления.
dgvCell = new DataGridViewTextBoxCell(); // code to remove checkbox
dgvCell.Value = string.Empty;
dgv_modi_del_trans.Rows[1].Cells[0] = dgvCell;