5

I am having a problem with the handling of an index changed event for a comboBox that resides inside a dataGridView. I write an method to handle the comboBox selection change using either a delegate:

ComboBox.SelectedIndexChanged -= delegate { ComboBoxIndexChanged(); };
ComboBox.SelectedIndexChanged += delegate { ComboBoxIndexChanged(); };

or an EventHandler:

comboBox.SelectedIndexChanged += new EventHandler(ComboBoxIndexChanged);

but both methods do not work as expected. That is, when you click on your selection within the comboBox (contained within the dataGridView) it takes multiple clicks to cause my ComboBoxIndexChanged(); method to function proper, that if it decides to function at all. What is the best way to overcome/go-about specifying an event on an indexedChange of a comboBox within a dataGridView?

The code I am currently using in context is as follows:

private void dataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    try
    {
        if (this.dataGridView.CurrentCell.ColumnIndex == (int)Column.Col)
        {
            ComboBox comboBox = e.Control as ComboBox;
            if (comboBox != null)
            {
                comboBox.SelectedIndexChanged += new EventHandler(ComboBoxIndexChanged);
            }
        }
        return;
    }
    catch (Exception Ex)
    {
        Utils.ErrMsg(Ex.Message);
        return;
    }
}

and the event ComboBoxIndexChanged is:

private void ComboBoxIndexChanged(object sender, EventArgs e)
{
    // Do some amazing stuff...
}

I have read a similar thread on StackOverFlow which states that there is a problem with dealing with the comboBox change event this way, but I cannot get the solution to work. The post can be found here: "SelectedIndexChanged" event in ComboBoxColumn on Datagridview. It says:

"Things get complicated since they optimized the DataGridView by only having one editing control for all the rows. Here's how I handled a similar situation:

First hook up a delegate to the EditControlShowing event:

myGrid.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(
                                Grid_EditingControlShowing);
...

Then in the handler, hook up to the EditControl's SelectedValueChanged event:

void Grid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    ComboBox combo = e.Control as ComboBox;
    if (combo != null)
    {
        // the event to handle combo changes
        EventHandler comboDelegate = new EventHandler(
          (cbSender, args) =>
            {
                DoSomeStuff();
            });

        // register the event with the editing control
        combo.SelectedValueChanged += comboDelegate;

        // since we don't want to add this event multiple times, when the 
        // editing control is hidden, we must remove the handler we added.
        EventHandler visibilityDelegate = null;
        visibilityDelegate = new EventHandler(
          (visSender, args) =>
            {
                // remove the handlers when the editing control is
                // no longer visible.
                if ((visSender as Control).Visible == false)
                {
                    combo.SelectedValueChanged -= comboDelegate;
                    visSender.VisibleChanged -= visibilityDelegate;
                }
            });

         (sender as DataGridView).EditingControl.VisibleChanged += 
           visibilityDelegate;
    }
}"

This issue I have with this is that "VisSender" is not defined hence the event "VisibleChanged" cannot be used.

Any help from you lads, is as always, most appreciated.

Community
  • 1
  • 1
MoonKnight
  • 23,214
  • 40
  • 145
  • 277
  • Why are you assinging the event handler in code? Is the select created dynamically? – James Johnson Aug 25 '11 at 16:43
  • Yes. Depending on the comboBox's value this effects other items in the dataGridView. – MoonKnight Aug 25 '11 at 16:50
  • Can you post some of the relevant markup? – James Johnson Aug 25 '11 at 16:53
  • I may have missunderstood you. I click on the comboBox column within the dataGridView (DGV), it drops down, I select a new index - that index is then used (via an Event handler) to set some other stuff. The DGV has many many rows (which can be added at runtime by the user), so I need an EventHandler to deal with thtese many possible changes accordingly. Thanks. – MoonKnight Aug 25 '11 at 17:11
  • If the dropdown is declared in your markup, you should just assign the event handler there. The technique you're using is only for dynamically created GridViews. – James Johnson Aug 25 '11 at 17:23
  • Perhaps I should have tagged WinForms; but no, that is not the case. I can dynamically create rows in this DGV at runtime, I can also specify them before compilation or a mixture of both. In both cases, the only way to deal with comboBoxes in a dataGridView remains to dynamically create an event handler. Thanks. – MoonKnight Aug 25 '11 at 17:52
  • Possible duplicate of [What event catches a change of value in a combobox in a DataGridViewCell?](http://stackoverflow.com/questions/5652957/what-event-catches-a-change-of-value-in-a-combobox-in-a-datagridviewcell) – Jim Fell Jun 15 '16 at 21:18

1 Answers1

13

Sounds like you want the changes to be committed as soon as the user changes the drop down box, without them having to click off of the cell. In order to do this you will need to force the commit when the change happens (using CommitEdit, there is also an example on the MSDN page). Add this to your DataGridView:

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

Then you could just listen for the CellValueChanged and avoid having to try and register for the ComboBoxValueChanged event on the underlying editing control.

SwDevMan81
  • 48,814
  • 22
  • 151
  • 184