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;
}