Como alternar entre DataGridViewTextBoxCell e DataGridViewComBOBoxCell?
Pergunta
Eu quero ter um DataGridView que tenha duas colunas. A primeira coluna sempre será do tipo DataGridViewCombOBoxColumn. Com base na seleção nessa coluna, gostaria de poder alterar a célula correspondente na segunda coluna para um DataGridViewComBOBOXCELL ou a um DataGridViewTextBoxCell.
Estou pensando que só preciso fazer a segunda coluna do tipo DataGridViewColumn, mas não entendo a mecânica de como alterar o tipo de célula em tempo real.
Estou trabalhando com o VB.NET no Visual Studio 2005.
Desde já, obrigado!
Atualizar: Uma maneira de contornar isso, suponho, é fazer a segunda coluna como uma DataGridViewCombObOxColumn e alterar os atributos da célula para que ela se comporte como uma lista suspensa ou como um menu suspenso (editável) sem elementos. O último se parece o suficiente com uma caixa de texto que eu poderia viver com ela e não envolveria alterar o tipo de célula.
Solução
Não tenho a versão VB.NET, mas espero que este snippet rápido C# o ajude ou aponteá na direção certa.
Neste exemplo, configurei um simples DataGridView com 2 colunas. O primeiro é um DataGridViewComboBox preenchido com duas opções: "Texto" ou "Combo".
A segunda coluna está inicialmente definida como DataGridViewTextBoxColumn do designer.
Eu lido com o evento CurrentCellDirTyStatechanged no DataGridView. Eu verifico se a célula está suja e verifique apenas a primeira coluna (o ComboBox). Você precisa chamar o Commitedit para obter o novo valor no combo, ou então estará analisando o valor anterior. Com base na seleção na caixa de combinação, substituo a célula na 2ª coluna com uma nova célula desse tipo.
Você adicionaria sua própria lógica (preencha as suspensas e lidaria com o valor). Você pode querer armazenar o valor e depois colocá -lo de volta na célula ou qualquer outra coisa.
Aqui está o código que usei e fiz um teste rápido e sujo em:
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();
}
}
}
Aqui está uma tradução rápida do VB, que eu testei e funciona.
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
Classe final
Você perderá qualquer valor armazenado nessa coluna, então precisará salvá -lo primeiro.
Jon
Outras dicas
Você pode criar seu próprio modelo de célula que hospeda um controle do usuário. No controle do usuário, você adiciona uma caixa de texto e um ComboBox e adiciona um método/propriedade para mostrar um e ocultar outro.
Esta amostra Cria uma célula de botão de rádio, não é difícil alterar o código para hospedar um controle do usuário.
dgvCell = new DataGridViewTextBoxCell(); // code to remove checkbox
dgvCell.Value = string.Empty;
dgv_modi_del_trans.Rows[1].Cells[0] = dgvCell;