Nov 19, 2008

DataGridView Comboboxes have troubles like tribbles

I was using a DataGridView control with a  combo box in one of the columns.  I needed to handle the SelectedIndexChanged event of the embedded combo box.  You can do that by handling the EditingControlShowing event and adding the SelectedIndexChantedEvent there. 

private void dgvMinMaxValues_EditingControlShowing(object sender,                                                                                 DataGridViewEditingControlShowingEventArgs e)

{
    ComboBox my_dgv_combo = e.Control as ComboBox;
    if (my_dgv_combo   != null)
    {
        //remove any previously added handlers
        my_dgv_combo.SelectedIndexChanged -= new EventHandler(combo_SelectedIndexChanged);
        my_dgv_combo.SelectedIndexChanged += new EventHandler(combo _SelectedIndexChanged);
    }
}
The MS documentation tells you more about using this technique. What it doesn't tell you is that the event is going to fire way more times than you will expect or want.   The SelectedIndexChanged event fires just once the first time you click on a combobox and change the value. However, anytime you change rows in the DataGridView the event fires twice. Clicking on the combo box in the new row causes the old event handler to fire two more times before the EditControlShowing  event fires.  So in effect you get five events for every one you really want. Maybe not too tribbly an experience if you're doing something trivial based on the combobox but if like me you're running through some data processing on potentially large data sets, you really need to avoid the extra events. Plus it just doesn't seem green to be doing all that extra work for no reason.
My workaround is to promote the embedded combo box to a member variable so in the EditControlShowing method you cast e.Control  to your member var:
_myDgvCombo  = e.Control as ComboBox;
Now in the RowLeave event for the DGV event I can remove the event handler. 
private void dgvMinMaxValues_RowLeave(object sender, DataGridViewCellEventArgs e)
{
    if (_myDgvCombo != null)
    {
        //remove any previously added handlers
        _myDgvCombo .SelectedIndexChanged -= new EventHandler(OnMyDgvCombo_SelectedIndexChanged);
    }
}
Now the event fires once everytime I change the Selected index. 

About Me

My photo
Tod Gentille (@todgentille) is now a Curriculum Director for Pluralsight. He's been programming professionally since well before you were born and was a software consultant for most of his career. He's also a father, husband, drummer, and windsurfer. He wants to be a guitar player but he just hasn't got the chops for it.