none
DataGridViewComboBoxColumn Selection Changed

    Question

  • Hi,
    I would like to handle the Selection Changed event of a ComboBox column inside my datagrid, what would be the best method to do it. I tried the CellValueChanged event but that throws up an error when I am loading the datagrid. Please suggest how to do this.

    Thanks,
    Kunal
    Wednesday, July 06, 2005 6:22 AM

Answers

  • In VB you don't need to recast it (unless you have option strict enabled). In C# you do. Here is the VB code:


    Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing

            Dim editingComboBox As ComboBox = e.Control
            AddHandler editingComboBox.SelectedIndexChanged, AddressOf Me.editingComboBox_SelectedIndexChanged

    End Sub
    Private Sub editingComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)

    End Sub

     


    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"




    Friday, July 08, 2005 12:35 AM
  • Thanks for the reply Mark, I think SelectionChangeCommitted should work for me once I get the Beta 2. In Beta 1 it isnt getting fired properly.
    Friday, July 08, 2005 5:54 AM

All replies

  • You need to handle the EditingControlShowing event on the DataGridView control and cast the editing control to a ComboBox. Then you can hook up the SelectionChanged event like normal.

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"
    Wednesday, July 06, 2005 11:48 PM
  • Hi Mark,

    The editing control is itself a ComboBox, so why should I recast it? Also, can you please give the code of how to hook up the SelectedChange event if I recast it?

    Thanks,
    Kunal
    Thursday, July 07, 2005 3:59 AM
  • In VB you don't need to recast it (unless you have option strict enabled). In C# you do. Here is the VB code:


    Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing

            Dim editingComboBox As ComboBox = e.Control
            AddHandler editingComboBox.SelectedIndexChanged, AddressOf Me.editingComboBox_SelectedIndexChanged

    End Sub
    Private Sub editingComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)

    End Sub

     


    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"




    Friday, July 08, 2005 12:35 AM
  • Hi Mark,
    I did what you told and in the event handler I just wrote a code for

    MessageBox.Show(CType(sender, ComboBox).SelectedIndex)

    Now this is what is happening.

    I click on the ComboBox column in the first row and change its value. and go to the next cell. The event does not get fired.

    Now I click on the same ComboBox again, and the MessageBox comes up twice.

    Then I click on the same ComboBox again, and the MessageBox comes up thrice.

    And so on. Thus the problem is two fold, the event handler is not called when the Index changes and secondly, it is called multiple times. Multiple times could be because the event handler is added every time, but why isnt it getting called when the index actually changes is something I couldnt find out.

    Even if I click on some other rows ComboBox column the same behaviour is repeated. Please suggest a way out, and also why is it not getting called when the index actually changes. I am using the Dec 2004 CTP build

    Thanks,
    Kunal

    [Edit] I modified the EditingControlShowing event as below. But now also the handler is getting called twice.

    Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
            Dim editingComboBox As ComboBox = e.Control
            Try
                RemoveHandler editingComboBox.SelectedIndexChanged, AddressOf Me.editingComboBox_SelectedIndexChanged
            Catch ex As Exception
                MessageBox.Show("Exception")
            End Try

            AddHandler editingComboBox.SelectedIndexChanged, AddressOf Me.editingComboBox_SelectedIndexChanged
        End Sub

    Friday, July 08, 2005 3:20 AM
  • yes - this is the result of the editing control being reused and the fact that the combobox is databound. the SelectionChangeCommitted event might be a better event for what you are trying to do.

    In newer builds this is the order when I get the messagebox for the SelectedIndexChanged event:
    1) I click on the ComboBox column in the first row and change its value -- I get the messagebox.
    2) when I goto the next cell I do not get the message.
    3) When I click on the same combobox again I do not get the message.
    4) If I select a different value in the same combobox I get the message
    5) If I select a different combobox on a different row I get 3 messageboxes: These are due to the cell's value being committed.

    I'm going to investigate if there is something we can do for this. Thanks for the feedback!

    -mark
    DataGridView Program Manager
    Microsoft
    This post is provided "as-is"
    Friday, July 08, 2005 5:44 AM
  • Thanks for the reply Mark, I think SelectionChangeCommitted should work for me once I get the Beta 2. In Beta 1 it isnt getting fired properly.
    Friday, July 08, 2005 5:54 AM
  • Hey Mark,
    To get rid of this problem(getting messages again again!) I made one private variable of type combo box and make sure that the event register only one time. Now the message I am getting is only one time.  Big Smile

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)

    {

    //This is private variable ComBoBox.

    if (combo == null)

    {

    combo = (ComboBox)e.Control;

    combo.SelectedIndexChanged +=new EventHandler(combo_SelectedIndexChanged);

    }

    }

    private void combo_SelectedIndexChanged(object sender, EventArgs e)

    {

    MessageBox.Show("Coming");

    }

    Monday, October 24, 2005 11:01 AM
  • HI Mark.

    I am working on same. And I get the same error. Do you get any solution now? Please response me.

    Thanks,
    Sachin

     

     

    Wednesday, November 15, 2006 5:37 PM
  • Hi,
    Do you get the solution for this..

    I am also facing the same problem.. But I don't know how to resolve this..

    Please send me sample code..

     

     

    Wednesday, November 15, 2006 10:02 PM
  • Hi

    I think Mark has already pointed out that you should use SelectionChangeCommitted event because it insures that user has finished with the item which he wants to selects.

    The annoying thing that the message is coming again and again; It is happening because EditingControlShowing event fires every time when you reach to the next row and you dare to edit the cell containing that control (combo box in this case). In order to prevent the message box from coming again and again you should first "Un-Wire" the event and then "Wire" the event. This way even though the editing control showing event get fired multiple times, we can be assured that our editing control is being wired only one time.

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)

    {

    //UnWire the code

    combo.SelectedIndexChanged -=new EventHandler(combo_SelectedIndexChanged);

    //Wire the code

    combo.SelectedIndexChanged +=new EventHandler(combo_SelectedIndexChanged);

    }

    Friday, November 24, 2006 2:22 PM
  •  

    Here is a slightly more complete example.

     

    The difference in this example to what has previously been discussed is that we do not keep a reference to the control in a private variable. There is no need to do that, and doing so produces a lot of potential for errors. Since the DataGridView is managing the combobox controls, there may be many of these controls, and even the same "logical control" (ie, to the user, the same combo box in the same row), may get destroyed or rebuilt at any time, by the DGV.  From our perspective, outside of the DataGridView, the only thing we are sure of is that the control referenced in the event args for EditingControlShowing is currently the one that the user is using...

     

    Instead of a private reference to the combobox, we keep a private reference to the EventHandler delegate for our SelectionChangeComitted event. There's no point in creating a two new delegates every time the control is clicked.

     

    I use this technique in my apps to control the row state conditionally based on the selections in various comboboxs. I call _dataGridView.EndEdit() in the SelectionChangeCommited event handler, to allow the other cells to react to the selection.

     

    Hope that helps,

    Troy

     

     

     

    Code Snippet

     

    public class Example

    {

    /// <summary>

    /// Constructor

    /// </summary>

    public Example()

    {

    _dataGridView = new DataGridView();

     

    // setup the datagridview here.

     

    // hook up editing control showing event

    _dataGridView.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(_dataGridView_EditingControlShowing);

     

    // create a delegate for the method that will handle the event

    _comboBoxSelectDelegate = new EventHandler(combo_SelectionChangeCommitted);

    }

     

    private DataGridView _dataGridView;

    private EventHandler _comboBoxSelectDelegate;

     

    void _dataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)

    {

    // get the control from the event args.

    ComboBox combo = e.Control as ComboBox;

     

    if (combo != null)

    {

    // remove the event subscription if it exists.

    combo.SelectionChangeCommitted -= comboSelectDelegate;

    // add a subscription to the event

    combo.SelectionChangeCommitted += comboSelectDelegate;

    }

    }

     

    void combo_SelectionChangeCommitted(object sender, EventArgs e)

    {

    // handle the event.

    ComboBox combo = sender as ComboBox;

     

    if (combo != null)

    {

    MessageBox.Show(

    string.Format("The combobox selected index is: {0}", combo.SelectedIndex)

    );

    }

    }

    }

     

     

     

    Monday, March 24, 2008 7:19 PM
  • Works great! Thank you!

    Sunday, November 15, 2009 3:50 AM
  •  Dim flag As Boolean = False
        Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles dgv_assign.EditingControlShowing
            If flag = False Then
                Dim editingComboBox As ComboBox = e.Control
                AddHandler editingComboBox.SelectionChangeCommitted, AddressOf Me.editingComboBox_SelectedIndexChanged
                flag = True
            End If

        End Sub
        Private Sub editingComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
            Try

                Dim r_index, c_index As Integer
                r_index = dgv_assign.SelectedCells(0).RowIndex
                c_index = dgv_assign.SelectedCells(0).ColumnIndex

                If dgv_assign.Columns(c_index).name = col_enterby.Name Then
                    Dim manager As String = Convert.ToString(dgv_assign.Rows(r_index).Cells(col_enterby.Name).EditedFormattedValue)
                    If IsNothing(ds_pmd.Tables("Load")) Then
                        LoadAssignes(manager)
                    Else
                        Dim dr() As DataRow = ds_pmd.Tables("Load").Select("pmd_manager='" & manager & "'")
                        If dr.Length = 0 Then
                            LoadAssignes(manager)
                        Else
                            BindingSource1.Filter = "pmd_manager='" & manager & "'"
                        End If
                    End If

                End If
            Catch ex As Exception
                PARAM_Class_Library.Modules.ParamGlobal.CreateLogFile("dgv_assign_CellValueChanged : " & ex.Message, LogFilePath)
                MessageBox.Show("dgv_assign_CellValueChanged: " & ex.Message, project_name, MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Sub
    Wednesday, April 06, 2011 12:30 PM
  • Hi Troy,

    I believe your above solution that uses a private reference to the EventHadler delegate is a very beatiful way to solve the problem resulted in handling SelectionChangeCommitted event. I got the same problem when I tried to handle the same event. But I can't translate your above solution in C# into VB. Can you or anybody else translate the solution for me?

    Thanks!

    Lao Fu


    /Chengde Fu/

    Saturday, August 18, 2012 10:56 PM
  • Thank you so much! It helped me a lot. It worked just the way I needed. 
    Monday, May 19, 2014 12:54 PM