0
votes

In a C# app, I have a DatagridView with all cells as DataGridTextBoxCol. Grid is populated dynamically with unbound values. Grid has different type of food items. My need is, when user clicks/wants to edit a cell - a combo box with list of food items appears in place of cell. If their is any value in cell, then that value should be selected in combo. User can type and item gets selected in combo. This is what I have tried so far:

private void PopulateAllergensCombo()
    {
        // Populate Combo box in Form_load & be hidden
        BindingSource allergensBindSource = new BindingSource();
        allergensList = dbOperations.GetAllergensListObjects();

        allergensBindSource.DataSource = allergensList;

        allergensCmb.DataSource = allergensBindSource.DataSource;   // allergensList;
        allergensCmb.DisplayMember = "Name";
        allergensCmb.ValueMember = "AllergensNumber";
    }

To place this combo allergensCmbin the current cell

        private void cellAssignments_dgv_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
    {
        DataGridViewCell dvCell = cellAssignments_dgv.CurrentCell;

        allergensCmb.Location = dvCell.ContentBounds.Location; // location of cell is X=0, Y=11 - This seems to be relevant from grid & not from Form

        if ( String.IsNullOrEmpty(cellAssignments_dgv.CurrentCell.Value.ToString()) == false )
            allergensCmb.SelectedValue = cellAssignments_dgv.CurrentCell.Value;
        allergensCmb.Show();
    }

As with the above dgv_CellBeginEditevent code, the combo doesn't show in the cell location. Location of the cell is X=0, Y=11 - 1st col 1st row cell. It's not relevant to the form dimensions. To get and set the value of item selected from combo in the grid cell, I tried implementing CellEndEdit and allergensCmb_SelectedIndexChanged events. But nothing works full 100%. With selectedIndexChanged event, I have lost the current cell as cell is no more active; can't get the current cell or if it is dirty!!

Any clue, how do I implement this type of control - show a Combobox on the current cell of the DataGridView. I did lots of research and tried out, but nothing works as expected.

Any help is highly appreciated.

////////////////////////////////////////// ************ UPDATIONS //////////////////////////////////////////

As you both suggested to use DataGridViewComboBoxColumn, I did:

// Add Columns
        for (int i = 1; i <= pair.Value.CellBodyRowData.Count; i++)
        {
            DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
            cbCol.HeaderText = i.ToString();
            cbCol.Name = i.ToString();

            cbCol.DataSource = allergensList;
            cbCol.ValueMember = "AllergensNumber";
            cbCol.DisplayMember = "Name";

            cellAssignments_dgv.Columns.Add(cbCol);

            // *** cellAssignments_dgv.Columns.Add((i.ToString(), i.ToString());
        }

// Populate in each Row
foreach (CellBodyRowData cbrData in cbRow.CellBodyRowData)
                {
                    // *****  dgvr.Cells[cbrData.Col - 1].Value = cbrData.CellAllergen.Name;

                    if (cbrData.CellAllergen.AllergensNumber > 0)
                        dgvr.Cells[cbrData.Col - 1].Value = cbrData.CellAllergen.AllergensNumber;
                    else
                        dgvr.Cells[cbrData.Col - 1].Value = 0;

                }

This is fine. In grid, I see each cell as ComboBox only. How do I make it show as normal text only and only while editing it appears as a combobox. And what is the reason to use EditingControlShowing event - I don't get that logic ?? I jut need to change the value & set a flag isCellAssignGridChanged to true, so can update the DB.

Can you please throw some light on this part.

Thanks

1
Rather than shuffling between a CBO and the DGV, you could add a DataGridViewComboBoxColumn to the gridŇɏssa Pøngjǣrdenlarp
Have you tried the editcontrolshowing event?Ctznkane525
If it is the same list, use the same DataSource and no extra overhead at all.Ňɏssa Pøngjǣrdenlarp
Make it a combobox rather than a text cell...u can default certain properties to make it look like a text box...then editcontrolshowing will workCtznkane525
Dropdownstyle to none?Ctznkane525

1 Answers

1
votes

Thanks @Plutonix and @JohnKane.

  1. I changed the cols to DataGridViewComboBoxColumn in the grid.
  2. Change the DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing; of the cols.
  3. Implemented EditingControlShowing event and changed the dropdown style cb.DropDownStyle = ComboBoxStyle.DropDownList;& SelectionChangeCommitted for the Combobox

    private void cellAssignments_dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        if (e.Control is ComboBox)
        {
            ComboBox cb = (ComboBox)e.Control;
            if (cb != null)
            {
                // Show the DropDown of the combo & set its event
                cb.DropDownStyle = ComboBoxStyle.DropDownList;
    
                cb.SelectionChangeCommitted -= cb_SelectionChangeCommitted;
                cb.SelectionChangeCommitted += cb_SelectionChangeCommitted;
            }
        }
    }
    
    void cb_SelectionChangeCommitted(object sender, EventArgs e)
    {
        ComboBox cb = (ComboBox)sender;
    
        if (cb != null)
        {
            Console.WriteLine("Selected Combo = " + cb.SelectedText + " Value = " + cb.SelectedValue);
    
            // Notify the cell is dirty
            cellAssignments_dgv.NotifyCurrentCellDirty(true);
            // Force to End Edit the Cell
            cellAssignments_dgv.EndEdit();
        }
    
    }
    
  4. Finally, in CellEndEdit event, implemented my update update the collection object

Hope this helps some one.

Regards,