How to detect the change in a datagridviewcomboboxcolumn in a new datagridview row?

How to detect the change in a datagridviewcomboboxcolumn unbound column in a new row?  I have 2 datagridviews on a form.  The first grid has a several columns bound to a dataset with the addition of a datagridviewcomboboxcolumn inserted.  (Side note, even though I inserted it at column index 0 and it displays first in the grid, its actual index is 6 for some reason).  The datagridviewcomboboxcolumn is bound to a list of items in a datatable.  What I want to happen is when a user selects a new value in this column in a new row or changes a value in this column on an existing row for and event to fire.  In this event I need to add some rows orupdate some rows in datagridview2 based on the value in the datagridviewcomboboxcolumn.  I have been trying to use this approach:

    Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
        Dim cb As ComboBox = e.Control
        If Not cb Is Nothing Then
            ' first remove event handler to keep from attaching multiple:
            RemoveHandler cb.SelectedIndexChanged, AddressOf Me.editingComboBox_SelectedIndexChanged
            ' now attach the event handler
            AddHandler cb.SelectedIndexChanged, AddressOf Me.editingComboBox_SelectedIndexChanged

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

The problem with this approach is this event gets fired for every row in the datagridview, not just the current row and then only after the focus has moved to a new "new row".  It does not fire on the actual change of the selection in the combocolumn.  I can't seem to find a list of the events in the order they happen when a user selects an item in a datagridviewcomboboxcolumn in a new row.
Who is Participating?
SanclerConnect With a Mentor Commented:
Where does the combo that we are concerned with get its Items collection from?  Your original post (which I've now re-read) referred to "a datagridviewcomboboxcolumn unbound column".  That's what I'd spotted and how I set up my test: i.e. by hardcoding some items into the combo.  But I now twig that it also said "datagridviewcomboboxcolumn is bound to a list of items in a datatable", so perhaps my test regime was wrong.

With the set-up I have I've not been able to reproduce the multiple firing to the extent you report.  I hadn't done a sequence like that you describe but when I've tried it now, I do get one "extra" report.  The "old" row I return to after a "new" row is reporting its existing selectedindex before I change that selection.  But I've overcome that with

    Private Sub myDataGridView_CellLeave(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles myDataGridView.CellLeave
        mycombo = Nothing
    End Sub

Can you try that, and see if it overcomes the problem?  If not, let me know the details of the binding set up and I'll have another think.

I think you need to make two changes.  First, you will need to use the EditingControl's events to detect changes as they are actually made rather than waiting until the edit is "committed" by the user moving to another column or row.  Second, I think you may find it neater to turn the facility you want on and off other than by adding and removing handlers.  Try this.  At form level add a declaration on these lines

    Private WithEvents mycombo As System.Windows.Forms.DataGridViewComboBoxEditingControl

Having done that, if you click on mycombo (or whatever name you use) in the top lefthand dropdown in the code window, SelectedIndexChanged will be selectable in the righthand dropdown, and you can code into that.  My test code was this

    Private Sub mycombo_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles mycombo.SelectedIndexChanged
    End Sub

Then, in the

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

change the code to something like this

        If TypeOf (e.Control) Is System.Windows.Forms.DataGridViewComboBoxEditingControl Then
            mycombo = e.Control
            If Not mycombo.DataSource Is Nothing Then 'SEE NOTE BELOW
                mycombo = Nothing
            End If
            mycombo = Nothing
        End If

The bit about the datasource is to restrict the "activation" of the SelectedIndexChanged code to the UNBOUND combobox column, as I'm not certain from your description whether you have some bound comboboxes in your datagridview as well.  If you don't, those three lines can go.

Although I've tested this, I must say that it's not something I've attempted before so I can't guarantee it's foolproof under real life conditions.  But, despite trying, I've not been able to break it so far.

bjmanleyAuthor Commented:

This does seem to work a little better than what I was trying.  It is firing when I need it to on a new row but when I try to change the value in the combobox for an existing row it is still firing multiple times.  looks like this is what is happening:
empty datagrid
click on new row
choose first item in the combo (item index 0)
works great
now on the new "new row"
click on arrow of combobox
message that index is -1(current row)
message that index is 0 (previous row's index)
message that index is 0 (previous row's index)
then dropdownlist is displayed
I choose an item
message that index is equal to the item I chose.(current row)

It appears that the event fires for whatever the previous combobox was even if it was several rows apart.  very strange.  I am also trying a new approach and it works consistently but requires a commit of the row either by moving focus to another row or by the enter key.

    Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
        Dim mycell As DataGridViewCell = DataGridView1(e.ColumnIndex, e.RowIndex)
        Dim myname As String = mycell.OwningColumn.Name.ToUpper
        If mycell.OwningColumn.Name.ToUpper = "PARAGRAPH" Then
        End If
    End Sub

If you have any other ideas for an alternative approach let me know.  What this form is supposed to accomplish is to let the user choose from a list of paragraphs in the combobox in dgv1.  When they choose the paragraph, if it has some parameters that need values I build a list of them and display them in dgv2.  When printing, I roll through dgv1, get each paragraph in the order displayed in dgv1, populate it with the values for that paragraph in dgv2 which the user entered and so on until I have assembled a complete document.  I could probably go with some time of a chooser setup with 2 listboxes and arrows to move the selections back and forth and others to reorder the list but initially this seemed to take up less realestate and allowed the user to just change each row to the selection they wanted and no need for buttons to change the order of the items in the list, they could just change the combo on each row if they wanted a different order.  This app builds legal documents.
bjmanleyAuthor Commented:
That appears to be it!  Great job! The combo is bound to another datatable.  There is one other column in dgv1 which is a button column and when selected it will display the full paragraph text in a popup for that paragraph key/brief description contained in the combo column using the DataGridView1_CellClick event and checking the column index .I have been struggling with this and I really appreciate your help on this as well as my previous question you worked on.  Too bad you didn't see my post on trying to make the text in the actual tab of a tab control page to display multiline/wordwrap instead of length question.  It went unanswered.  Thanks again!

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.