What event catches a change of value in a combobox in a DataGridViewCell?
Asked Answered
C

5

40

I want to handle the event when a value is changed in a ComboBox in a DataGridView cell.

There's the CellValueChanged event, but that one doesn't fire until I click somewhere else inside the DataGridView.

A simple ComboBox SelectedValueChanged does fire immediately after a new value is selected.

How can I add a listener to the combobox that's inside the cell?

Circlet answered 13/4, 2011 at 17:9 Comment(0)
B
76

The above answer led me down the primrose path for awhile. It does not work as it causes multiple events to fire and just keeps adding events. The problem is that the above catches the DataGridViewEditingControlShowingEvent and it does not catch the value changed. So it will fire every time you focus then leave the combobox whether it has changed or not.

The last answer about CurrentCellDirtyStateChanged is the right way to go. I hope this helps someone avoid going down a rabbit hole.

Here is some code:

// Add the events to listen for
dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);



// This event handler manually raises the CellValueChanged event 
// by calling the CommitEdit method. 
void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dataGridView1.IsCurrentCellDirty)
    {
        // This fires the cell value changed handler below
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
}

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // My combobox column is the second one so I hard coded a 1, flavor to taste
    DataGridViewComboBoxCell cb = (DataGridViewComboBoxCell)dataGridView1.Rows[e.RowIndex].Cells[1];
    if (cb.Value != null)
    {
         // do stuff
         dataGridView1.Invalidate();
    }
}
Brett answered 23/1, 2014 at 23:48 Comment(5)
Thank you. I've seen numerous examples using the EditedControlShowing method, but I even ended up crashing .NET with it due to probably recursive events.Undersize
@Brett Hai. I'm quite new in C#. Where should i put the events to listen for? I am not quite understand this part.Confusion
guys - pay attention that this answer - actually tells You to see an answer at bottom :) Save Your time :))))))Elodia
Hi, I tried this method, but it fires multiple times when I changed only 1 comboboxcell.Villainous
How do you actually get which cell is the dirty cell though? The event args contain no row or column info.Ambrogio
S
18

You can also handle the CurrentCellDirtyStateChanged event which gets called whenever a value is changed, even if it's not commited. To get the selected value in the list, you would do something like:

var newValue = dataGridView.CurrentCell.EditedFormattedValue;
Sigmoid answered 13/4, 2011 at 17:46 Comment(1)
amazing answer ! it saved me ! in my case also required additional check : have two events happening when selecting and when going to new cell -old one raises the same event again: but correct event easily found by checking .Focused property of Combo. Thanks a lot !!!Elodia
T
14

This is the code, which will fire the event of the selection in the comboBox in the dataGridView:

public Form1()
{
    InitializeComponent();

    DataGridViewComboBoxColumn cmbcolumn = new DataGridViewComboBoxColumn();
    cmbcolumn.Name = "cmbColumn";
    cmbcolumn.HeaderText = "combobox column";
    cmbcolumn.Items.AddRange(new string[] { "aa", "ac", "aacc" });
    dataGridView1.Columns.Add(cmbcolumn);
    dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
}

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    ComboBox combo = e.Control as ComboBox;
    if (combo != null)
    {
        combo.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged);
        combo.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged);
    }
}

private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    ComboBox cb = (ComboBox)sender;
    string item = cb.Text;
    if (item != null)
        MessageBox.Show(item);
}
Tocopherol answered 13/4, 2011 at 17:28 Comment(2)
It works but as @Brett said, it throws too many events. It worked for some times but in some cases it fails and raise a fatal error of type InvalidOperationException: Operation is not valid because it results in a reentrant call to the SetCurrentAddressCore function. I used @Brett 's solution and now everithing works fineOutroar
thanks for the solution @MitjaBonca but what if I have two comboboxcolumns in datagridview.Bongbongo
A
2

I have implemented another solution, that seems more responsive (e.g.. quicker and less clicks) than Mitja Bonca's above. Although sometimes the combobox closes to quickly. This uses the CurrentCellDirtyStateChanged and CellMouseDown callback

private void myGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (myGrid.CurrentCell is DataGridViewComboBoxCell)
    {
        myGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
        myGrid.EndEdit();
    }
}

private void myGrid_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
    if (myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
    {
        myGrid.CurrentCell = myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
        myGrid.BeginEdit(true);
        ((ComboBox)myGrid.EditingControl).DroppedDown = true; // Tell combobox to expand
    }
}
Amorette answered 14/4, 2021 at 19:55 Comment(0)
P
-6
ComboBox cmbBox = (ComboBox)sender;                
MessageBox.Show(cmbBox.SelectedValue.ToString());
Pleasure answered 22/6, 2015 at 7:32 Comment(1)
@Sumett This might work, but which event should the code to be placed? Many of the event handlers change what the Sender and EventArgs are or what you might be able to cast the EventArgs to. Without the context, sorry this answer is rather useless. Why not provide the event...? Without the context, would suggest anyone not waste time with this answer.Alston

© 2022 - 2024 — McMap. All rights reserved.