Having an issue with a datagridview combobox being cleared when the currentcell is set

Pat Hanks 141 Reputation points
2023-10-01T19:22:24.0166667+00:00

I have run into an issue that has me stumped and I can't find any articles that references this issue. What I have is the EditingControlShowing event handler is setting up the event combox SelectedIndexChanged for the combox control. The handler executes the setting of the next cell. For clarity the first column is the category, which raises the SelectedIndexChanged event. Once the event has fired, the category combox is cleared. There is no text visible as well the selectedIndex is 0. I tried sending a tab but that had the same issue.

I need help to advance to the next cell when the user selects a category from the dropdown.

Below are the events in question.

private void ComponentsDataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
	if ((_formLoaded) & !_suppressEventFlags.ComponentsDataGridView)
	{
		if (e.Control is DataGridViewComboBoxEditingControl)
		{
			DataGridViewComboBoxEditingControl categoryComboBox = e.Control as DataGridViewComboBoxEditingControl;
			categoryComboBox.SelectedIndexChanged -= Combobox_SelectedIndexChanged;
			categoryComboBox.SelectedIndexChanged += Combobox_SelectedIndexChanged;
		}
	}
}

private void Combobox_SelectedIndexChanged(object sender, EventArgs e)
{
	int nextRowIndex = (ComponentsDataGridView.CurrentRow.Index + 1);
	int nextColumnIndex = 0;
	nextColumnIndex = ComponentsDataGridView.CurrentCell.ColumnIndex + 1;
	int lastColumnIndex = ComponentsDataGridView.DisplayedColumnCount(false);
	if (ComponentsDataGridView.CurrentCell.OwningColumn.Name == UOMColumnName)
	{
		//ComponentsDataGridView.CurrentCell = ComponentsDataGridView.Rows[nextRowIndex].Cells[0];
	}
	else
	{
		if ((nextColumnIndex > 0) & (nextColumnIndex <= lastColumnIndex)) 
		{ 
			ComponentsDataGridView.CurrentCell = ComponentsDataGridView.Rows[rowIndex].Cells[nextColumnIndex]; 
		}
		//if (nextColumnIndex > 0) { SendKeys.Send("{Tab}"); }
	}
}

Developer technologies | C#
{count} votes

Accepted answer
  1. KOZ6.0 6,735 Reputation points
    2023-10-02T06:20:56.0966667+00:00

    If you don't want to inherit DataGridView, what you'll catch is the DataGridView's CurrentCellDirtyStateChanged event, not the SelectIndexChanged event.

    private void ComponentsDataGridView_CurrentCellDirtyStateChanged(
                                    object sender, EventArgs e) {
        var dgv = (DataGridView)sender;
        var current = dgv.CurrentCell;
        if (dgv.IsCurrentCellDirty && current is DataGridViewComboBoxCell) {
            dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
            DataGridViewCell nextCell = GetNextCell(current, true);
            if (nextCell != null) {
                dgv.CurrentCell = nextCell;
            }
        }
    }
    
    private static DataGridViewCell GetNextCell(
                    DataGridViewCell current, bool excludeReadOnly) {
        var dgv = current.DataGridView;
        var column = current.OwningColumn;
        var rowIndex = current.RowIndex;
        var excludeState = excludeReadOnly ?
                                DataGridViewElementStates.ReadOnly :
                                DataGridViewElementStates.None;
        var nextColumn = dgv.Columns.GetNextColumn(
                                column,
                                DataGridViewElementStates.Visible,
                                excludeState);
        DataGridViewCell nextCell = null;
        if (nextColumn == null) {
            if (rowIndex + 1 < dgv.RowCount) {
                nextColumn = dgv.Columns.GetFirstColumn(
                                      DataGridViewElementStates.Visible,
                                      excludeState);
                nextCell = dgv[nextColumn.Index, rowIndex + 1];
            }
        } else {
            nextCell = dgv[nextColumn.Index, rowIndex];
        }
        return nextCell;
    }
    

1 additional answer

Sort by: Most helpful
  1. KOZ6.0 6,735 Reputation points
    2023-10-02T01:32:39.55+00:00

    Calling DataGridView.ProcessTabKey moves to the next cell, but unfortunately it is a protected method. You can do the following in a class that inherits DataGridView.

    internal class DataGridViewEx : DataGridView
    {
        protected override void OnCurrentCellDirtyStateChanged(EventArgs e) {
            base.OnCurrentCellDirtyStateChanged(e);
            if (IsCurrentCellDirty && CurrentCell is DataGridViewComboBoxCell) {
                CommitEdit(DataGridViewDataErrorContexts.Commit);
                ProcessTabKey(Keys.Tab);
            }
        }
    }
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.