Need help with DataGridViewComboBox and selecting the next control

Pat Hanks 60 Reputation points
2024-05-24T17:30:04.13+00:00

I need some help to achieve some functionality in a DataGridView. This Windows app is written in C# using the Windows Form App (.NET Framework). The DataGridView uses a mix of DataGridViewTextBoxColumn & DataGridViewComboBoxColumn. The need is to have the functionality when the user has selected a item from one of the DataGridViewComboBox to move to the next cell and if it is a DataGridViewComboBox to cause the dropdown to occur. In the app there will be many columns and thish would speed up data entry if I can get it working,

I have the below test code to work though this issue. The 2 problems I have are; First issue is when you first select an item from the Category combobox, the next column Sub Category is selected but the value is not updated in the Category combobox, it is blank. If you select the item again it will update the value. The second issue is I can’t figure out a way to cause the dropdown to occur as at that point the DataGridViewComboBox has not been selected yet.

Below is my test code. I would appreciate any help.

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;

// use this article as the basis
// https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/get-and-set-the-current-cell-wf-datagridview-control?view=netframeworkdesktop-4.8

namespace DatagridViewTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            SubscribeEvents();
            BindProducts();
        }

        private void SubscribeEvents()
        {
            this.MainDataGridView.EditingControlShowing += new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(ComponentsDataGridView_EditingControlShowing);
        }


        public void BindProducts()
        {
            List<Product> products = GetProducts();
            DataGridViewComboBoxColumn combobox = (DataGridViewComboBoxColumn)MainDataGridView.Columns["Category"];
            DataGridViewComboBoxColumn subCategory = (DataGridViewComboBoxColumn)MainDataGridView.Columns["SubCategory"];

            combobox.DisplayMember = "Name";
            combobox.ValueMember = "ID";
            combobox.DataSource = GetCategories();

            subCategory.DisplayMember = "Name";
            subCategory.ValueMember = "ID";
            subCategory.DataSource = GetSubCategories();

            MainDataGridView.DataSource = products;
        }

        private List<Product> GetProducts()
        {
            return new List<Product>
            {
                new Product{ Name = "Milk", Price=10.5, CategoryID=1, SubCategoryID=1  },
                new Product{ Name = "Rice", Price=14.5, CategoryID=2, SubCategoryID=2 },
                new Product{ Name = "Oil", Price=10.5, CategoryID=2, SubCategoryID=3}

            };
        }

        private List<Category> GetCategories()
        {
            return new List<Category>
            {
                new Category{ ID=1, Name="Dairy"},
                new Category{ ID=2, Name="Grocery"},
                new Category{ ID=3, Name="Category 3"}
            };

        }

        private List<Category> GetSubCategories()
        {
            return new List<Category>
            {
                new Category{ ID=1, Name="Milk"},
                new Category{ ID=2, Name="White Rice"},
                new Category{ ID=3, Name="Plant Based"}
            };

        }

        private void ComponentsDataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is DataGridViewComboBoxEditingControl dgvCBO)
            {
                dgvCBO.DropDownClosed -= CategoryCBO_DropDownClosed;
                dgvCBO.DropDownClosed += CategoryCBO_DropDownClosed;
            }
        }

        private void CategoryCBO_DropDownClosed(object sender, EventArgs e)
        {
            try
            {
                if (MainDataGridView.CurrentCell.ColumnIndex < MainDataGridView.DisplayedColumnCount(false))
                {
                    Debug.WriteLine("Current Cell[" + MainDataGridView.CurrentCell.ColumnIndex + "][" + MainDataGridView.CurrentCell.RowIndex + "]");
                    //
                    // When the next line executes, the next cell is selected, but the previous cell is not updated.  If you select the previous cell and change it,
                    // it will update.
                    //
                    MainDataGridView.CurrentCell = MainDataGridView[MainDataGridView.CurrentCell.ColumnIndex + 1, MainDataGridView.CurrentCell.RowIndex];
                    //MainDataGridView.CurrentCell = MainDataGridView.Rows[MainDataGridView.CurrentCell.RowIndex].Cells[MainDataGridView.CurrentCell.ColumnIndex + 1];
                    Debug.WriteLine("Current Cell[" + MainDataGridView.CurrentCell.ColumnIndex + "][" + MainDataGridView.CurrentCell.RowIndex + "]");

                    //*****************************************************************
                    // need a way to set the DroppedDown to true for the next combobox
                    //*****************************************************************
                    
                    //DataGridViewCell curCell = MainDataGridView.CurrentCell;

                    //DataGridViewComboBoxCell comboBoxCell = MainDataGridView.Rows[MainDataGridView.CurrentCell.RowIndex].Cells[MainDataGridView.CurrentCell.ColumnIndex] as DataGridViewComboBoxCell;
                    //if (comboBoxCell != null && comboBoxCell.EditType == typeof(DataGridViewComboBoxEditingControl))
                    //{
                    //    DataGridViewComboBoxEditingControl editingControl = MainDataGridView.EditingControl as DataGridViewComboBoxEditingControl;
                    //    if (editingControl != null)
                    //    {
                    //        editingControl.DroppedDown = true;
                    //    }
                    //}

                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }



    }
}

// From Products.cs
namespace DatagridViewTest
{
    internal class Product
    {
        public string Name { get; set; }
        public double Price { get; set; }
        public int CategoryID { get; set; }
        public int SubCategoryID { get; set; }
    }
    public class Category
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
    public class SubCategory
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,865 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,516 questions
{count} votes

Accepted answer
  1. KOZ6.0 6,210 Reputation points
    2024-05-24T19:38:25.2633333+00:00

    To find the next cell,

    DataGridViewColumnCollection.GetNextColumn/GetFirstColumn,DataGridViewRowCollection.GetNextRow

    It is better to use

    private static DataGridViewCell GetNextCell(DataGridViewCell currentCell) {
        var dataGridView = currentCell.DataGridView;
        var currentColumn = currentCell.OwningColumn;
        var currentRowIndex = currentCell.RowIndex;
        var nextRowIndex = currentRowIndex;
        var nextColumn = dataGridView.Columns.GetNextColumn(
                currentColumn, DataGridViewElementStates.Visible,
                               DataGridViewElementStates.None
            );
        if (nextColumn == null) {
            nextRowIndex = dataGridView.Rows.GetNextRow(currentRowIndex, 
                                                        DataGridViewElementStates.Visible);
            if (nextRowIndex != -1) {
                nextColumn = dataGridView.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            }
        }
        if (nextRowIndex != -1 && nextColumn != null) {
            return dataGridView[nextColumn.Index, nextRowIndex];
        } else {
            return null;
        }
    }
    

    To fire the dropdown of the DataGridViewComboBoxCell, put it in the edit state.

    private void CategoryCBO_DropDownClosed(object sender, EventArgs e) {
        var nextCell = GetNextCell(MainDataGridView.CurrentCell);
        if (nextCell != null) {
            MainDataGridView.CurrentCell = nextCell;
            if (nextCell is DataGridViewComboBoxCell) {
                MainDataGridView.BeginEdit(true);
                if (MainDataGridView.EditingControl is DataGridViewComboBoxEditingControl combobox) {
                    combobox.DroppedDown = true;
                }
            }
        } else {
            SelectNextControl(MainDataGridView, true, true, true, true);
        }
    }
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful