Search code examples
c#.netwinformsdatagridviewdatagridviewcombobox

WinForms DatagridViewComboboxColumn "enter key"


I have a datagridview with an editable combobox column, but everytime I press "Enter" on the current combobox, the text I'm writing disappears.

private void dgView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
    if (dgView1.CurrentCell.IsInEditMode)
    {
        if (dgView1.CurrentCell.GetType() == typeof(DataGridViewComboBoxCell))
        {
            if (!((DataGridViewComboBoxColumn)dgView1.Columns[e.ColumnIndex]).Items.Contains(e.FormattedValue))
            {

                ((DataGridViewComboBoxColumn)dgView1.Columns[e.ColumnIndex]).Items.Add(e.FormattedValue);
            }
        }
    }
}

private void dgView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (e.Control.GetType() == typeof(DataGridViewComboBoxEditingControl))
    {
        ComboBox cbo = (ComboBox)e.Control;
        cbo.DropDownStyle = ComboBoxStyle.DropDown;                 
    }
}

I also tried adding the event handlers: "on key press", "on key down" and "on key up" but same problem happens.

How can I keep the current text when I press "Enter" key?


Solution

  • The DataGridViewComboBoxColumn does not accept any value which is not contained in the Items collection. So when user types in a new value, the current cell does simply not store the value after editing. You have to find another way to get the last value right after cell being edited. We can get the actual DataGridViewComboBoxEditingControl in the EditingControlShowing event handler, that control is actually a ComboBox, we can handle the TextChanged event. The best DataGridView event to handle to submit the new value (add to Items and show in the current cell) is the CellEndEdit event. So here is the code you should do, I've tested it and looks like it works as what you expected:

    //use some variable to store the last edited value
    string editingValue;
    //EditingControlShowing event handler
    private void dataGridView1_EidtingControlShowing(object sender, 
                                      DataGridViewEditingControlShowingEventArgs e) {
      var combo = e.Control as ComboBox;
      if(combo != null){
         combo.DropDownStyle = ComboBoxStyle.DropDown;
         combo.TextChanged += (s,ev) => {
           editingValue = combo.Text;
         };
      }
    }
    //CellEndEdit event handler for your dataGridView1
    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e){
      var comboColumn = dataGridView1.Columns[e.ColumnIndex] as DataGridViewComboBoxColumn;
      if(comboColumn != null && editingValue != "" && 
         !comboColumn.Items.Contains(editingValue)){
         comboColumn.Items.Add(editingValue);
         dataGridView1[e.ColumnIndex, e.RowIndex].Value = editingValue;
      }
    }
    

    Note that the cell value is supposed to be string which is why the editingValue is declared as string, otherwise, you may have to convert the Text of the editing comboBox to the correct type of editingValue.