none
A problem with datagridview combobox RRS feed

  • 問題

  • Hi, friends..
    I have a problem relating to datagridview combobox..

    I have a datagridview binded with a customer datatable, one of datagridview columns is combobox which uses student datatable as a datasource (means: datagridViewCombobox.datasource= studentDatatable)..

    Now, when the user adds a new row to the datagridview, and selects a student name from the combobox, everything goes fine, and the new row is added to the customer datatable normally..

    but, when the user wants to add a new name which isn't one of the student names including in combobox list by typing the name manually, the combobox doesn't accept the new entry and the new row isn't added to the datagridview.

    So, how to make the datagridview combobox behaves as a datagridview textbox when the user enters a custom value which doesn't belong the values found in the combobox list. (in other words: how to make datagridview combobox accepts the entering by selecting an item from its list, and in the same time accept the entering manually by the user.)

    I use VS 2010..

    Thank you so much..
    • 已移動 CoolDadTx 2019年11月18日 下午 02:47 Winforms related
    2019年11月18日 上午 10:37

所有回覆

  • Hi SonOfNet,
    You should set the property DropDownStyle to DropDown, which enable typing in the combo box.
    Then use the CellValidating event handler to add the value to the items.
    You can refer to the following code.

    DataGridViewComboBoxColumn comboBoxColumn = new DataGridViewComboBoxColumn();
    private void Form1_Load(object sender, EventArgs e)
    {
        comboBoxColumn.HeaderText = "Student";
        comboBoxColumn.Width = 100;
        comboBoxColumn.Name = "comboBoxColumn";
        dataGridView1.Columns.Add(comboBoxColumn);
    
    }
    private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
    {
    
        if (e.ColumnIndex == comboBoxColumn.DisplayIndex)
        {
            if (!this.comboBoxColumn.Items.Contains(e.FormattedValue))
            {
                this.comboBoxColumn.Items.Add(e.FormattedValue);
            }               
        }
    }
    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        if (this.dataGridView1.CurrentCellAddress.X == comboBoxColumn.DisplayIndex)
        {
            ComboBox cb = e.Control as ComboBox;
            if (cb != null)
            {
                cb.DropDownStyle = ComboBoxStyle.DropDown;
            }
        }
    }

    Best Regards,
    Daniel Zhang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2019年11月19日 上午 08:48
  •   

    Hi,  Daniel Zhang..

    Thank you so much for your response.. the solution you've given doesn't work if a datagridview combobox's datasource property set to a datatable. So, your solution works fine if the combobox datasource set to null..

    The datagridview combobox datasource in my application set to a student datatable, this means the combobox list, in my application, contains object items, which are datarows, instead of string items.

    So, If I try to use :

    this.comboboxColumn.Items.Contains(e.FormattValue)

    The result is always false, because the C# compiler compares a string value (e.FormattedValue) against objects (Datarows)..

    As well as, the following code line:

    this.comboboxColumn.Items.Add(e.FormattedValue)

    doesn't work if the combobox's datasource set.


    2019年11月19日 下午 04:32
  • Hi SonOfNet,
    You can add the combobox control to the cell. When the new row is selected, it will trigger the SelectionChanged event. And then the combobox control will be added to the new row.
    Here is the code you can refer to.

    private void Form1_Load(object sender, EventArgs e) { DataTable dt = new DataTable(); dt.Columns.Add("name"); dt.Columns.Add("student"); this.dataGridView1.DataSource = dt; } private void dataGridView1_SelectionChanged(object sender, EventArgs e) { ComboBox combo = new ComboBox(); combo.DataSource = new List<string> { "a", "b", "c", "d" }; this.dataGridView1.Controls.Add(combo); combo.Location = this.dataGridView1.GetCellDisplayRectangle(1, dataGridView1.CurrentCell.RowIndex, true).Location; combo.Size = this.dataGridView1.GetCellDisplayRectangle(1, dataGridView1.CurrentCell.RowIndex, true).Size; }

    Best Regards,
    Daniel Zhang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    2019年11月20日 上午 08:02
  • I have a similar issue and looking at Daniel Zhang's post I can get close however in the "SelectionChanged" event, the range is initialized as new list. I want to take range that is already existing in a datagridviewcomboboxcell and simply add to it.

    I have found the developers manual says to try this:

    private void dataGridView1_CellValidating(object sender,
    		 DataGridViewCellValidatingEventArgs e)
    {
        if (e.ColumnIndex == comboBoxColumn.DisplayIndex)
        {
            if (!this.comboBoxColumn.Items.Contains(e.FormattedValue))
            {
                this.comboBoxColumn.Items.Add(e.FormattedValue);
            }
        }
    }
    
    private void dataGridView1_EditingControlShowing(object sender,
    		DataGridViewEditingControlShowingEventArgs e)
    {
        if (this.dataGridView1.CurrentCellAddress.X == comboBoxColumn.DisplayIndex)
        {
            ComboBox cb = e.Control as ComboBox;
            if (cb != null)
            {
                cb.DropDownStyle = ComboBoxStyle.DropDown;
             }
        }
    }
    
    ...however I cannot figure out the items.add command actually updates my datagridview (where does comboboxColumn come from???)

    2020年1月10日 下午 05:55
  • Hello,

    The following zip file is for Visual Studio 2017 or higher but older version can work with minor modifications. A DataTable is not used although will work fine with a DataTable. When data added during a session needs to be remembers be it in a database table or other source that is also read from when loading the data is not presented, only a comment where to perform updates.

    The first column is a DataGridViewComboBox column setup as auto complete and logic to add an item typed in if it does not exists. When adding a new row the default value for the DataGridViewComboBox column is the current month name. Note one column value is Karen which was added via typing in Karen with the drop down and since Karen was not in the list Karen was added.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    2020年1月11日 下午 12:24
    版主
  • Thanks Karen for code so I can track variables a little better to understand.

    One difference is that I am trying to use a datagridview that has a mix of text entries and comboboxcell entries. When attempting to adopt your code, I get hung up when trying to cast my datagridview.column(0) as a datagridviewcomboboxcolumn (see error below)

    Error: "Unable to cast object of type 'System.Windows.Forms.DataGridViewTextBoxColumn' to type 'System.Windows.Forms.DataGridViewComboBoxColumn'."

    Code seems good up to there as it will add new entry to drop down of datagridviewcomboboxcell but not the cells datasource? I have tried casting as comboboxcell but getting bogged down in the workaround...Any help? 

    Thanks again!

    2020年1月16日 下午 09:04
  • Unsure where this is happened but here are some tips.

    In EditingControlShowing note I use 

    if (dataGridView1.CurrentCell.IsComboBoxCell())

    Which means the code in the if statement only runs if the current cell EditType is 

    typeof(DataGridViewComboBoxEditingControl))

    Then in CellLeaving event if the first column is not a DataGridViewComboBox an exception will be thrown on this line

    var cb = (DataGridViewComboBoxColumn)(DataGridView1.Columns[0]);

    If the ComboBox is in a different column then change it e.g. if in column 5 we use 

    var cb = (DataGridViewComboBoxColumn)(DataGridView1.Columns[4]);



    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    2020年1月17日 上午 12:10
    版主
  • Ok, yeah we are definitely talking about same exception when setting cb. Let me give you a little more info. My datagridview is only one column and each row has a row header (sorry, having issue loading image). This means that Column(0) is the "Value" column and comprised of text entries and drop downs. Adopting your code, I can now type in the drop down fields (EditingControlShowing Event), but when I click away (CellLeave Event), I get hung up on mentioned exception. My thought is that I can't cast Column(0) as datagridviewcomboboxcolumn because it has text entries as well as dropdowns. This led me to a few attempts at casting as datagridviewcomboboxcell with no luck. Any thoughts for this case with mixed cell entry types?
    2020年1月17日 下午 01:14