1

I have a DGV in VB.Net 2008 connected to an Access DB table. The DGV is not Read Only, but is full of read-only columns except for one, which contains a combo box. The combo box allows the user to select an outcome for that particular row, and then the program copies in a pre calculated value into the "Profit" column depending upon the item selected in the combobox. Then the user hits the Save button and the DB updates (currently via SQL methods in the XSD).

Easy enough so far.

Here is the code.

Private Sub DGUserBets_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DGUserBets.EditingControlShowing

    Dim combo As ComboBox = CType(e.Control, ComboBox)

    If (combo IsNot Nothing) Then

         // Remove an existing event-handler, if present, to avoid 
         // adding multiple handlers when the editing control is reused.
        RemoveHandler combo.SelectedIndexChanged, _
            New EventHandler(AddressOf DGUBStake_SelectedIndexChanged)

        // Add the event handler. 
        AddHandler combo.SelectedIndexChanged, _
            New EventHandler(AddressOf DGUBStake_SelectedIndexChanged)

    End If

End Sub


Private Sub DGUBStake_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)

    Dim myStatus As ComboBox = CType(sender, ComboBox)

    Dim row = DGUserBets.CurrentRow

    Select Case myStatus.SelectedIndex
        Case 0
            row.Cells("DGUBProfit").Value = 0
            // pending. no action
        Case 1
            row.Cells("DGUBProfit").Value = row.Cells("DGUBIfWin").Value
            // win
        Case 2
            // loses
            row.Cells("DGUBProfit").Value = row.Cells("DGUBIfLose").Value
        Case 3
            // void
            row.Cells("DGUBProfit").Value = 0
    End Select


End Sub

The problem I have is that it would seem that if a user selects the desired outcome from the combobox but does NOT hit Enter, and simply mouses on to a different combobox to again select the outcome for a different row, the first eventhandler is not disconnected and thus the events fire multiple times. This then causes various default MsgBox errors and brings up problems when the user tries to commit all changes to the DB/exit program etc etc.

What do I need to do? Do I need to .EndEdit somewhere appropriate to force the row to save the changes? And where should I call this?

Thank you.

user57087
  • 147
  • 2
  • 4
  • 9

5 Answers5

2

A quick glance at the code brings up this question: If you create a new EventHandler when removing the existing one is it the same one?

Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
  • Hmm.. the EditControlShowing code is from MSDN. Do you think I might not be implementing it correctly? http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcomboboxeditingcontrol.aspx – user57087 Feb 24 '09 at 17:28
  • When you use AddHandler you don't save the created EventHandler anywhere. Do that and use that reference when calling RemoveHandler. – Sani Huttunen Feb 24 '09 at 17:37
  • On the other hand: You shouldn't even need to use New EvenHandler: RemoveHandler combo.SelectedIndexChanged, AddressOf DGUBStake_SelectedIndexChanged AddHandler combo.SelectedIndexChanged, AddressOf DGUBStake_SelectedIndexChanged should do. – Sani Huttunen Feb 24 '09 at 17:46
2

I have had a similar issue, add a handler for CellLeave if the cell being exited is the cell you are looking for (IE e.ColumnIndex = myEditableColumn.Index) then call gv.EndEdit()

Also I would recommend making the handlers member variables for assignment and removal because it seems nicer then always saying Remove New and Add New.

Quintin Robinson
  • 81,193
  • 14
  • 123
  • 132
  • Ahh I see!! I have now saved the Handler variable with the code I have posted below. Can you give me a little more clues with the CellLeave handler please?? Thanks! – user57087 Feb 24 '09 at 17:58
  • Sorry - I misread this at first and now see what you mean, I just need to add the code in the DGV's _CellLeave don't I? thanks. – user57087 Feb 24 '09 at 18:06
  • Sorry I got distracted for a while, Yes if you add a handler in the DGVs CellLeave and then you can handle when it is the particular column you are trying to enforce changes.. when it hits and meets the condition call EndEdit on the DGV and it should force the changes. – Quintin Robinson Feb 24 '09 at 18:28
0

I know this is an archaic post, but after buggering around with this same problem for half a day I've found a way to solve this another way, so I thought it would be worth sharing.

Adding a second handler to handle the leave event of the combobox which then removes the handler of selectedvalue changed. Appears to work quite slick, and unlike another option i found gives the desired resulting action (unlike removing the value changed handler on the actual handling event which then won't fire if you re-select from the same combobox)

Private LastEventHandler As EventHandler = AddressOf Me.ComboBoxValueChanged

Private Sub dgvThisDatagrid_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvOutstandingReminders.EditingControlShowing

    If TypeOf (e.Control) Is ComboBox Then
        Dim cboThisComboBox = DirectCast(e.Control, ComboBox)

        AddHandler cboThisComboBox.SelectedValueChanged, LastEventHandler

        AddHandler cboThisComboBox.Leave, AddressOf RemoveValueChangedHandler

    End If

End Sub

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

    If TypeOf (sender) Is ComboBox Then
        Dim cboThisComboBox = DirectCast(sender, ComboBox)

        MessageBox.Show("Value = " & cboThisComboBox.SelectedValue.ToString() & Environment.NewLine & "Text = " & cboThisComboBox.Text) ' Display index
    End If

End Sub

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

    If TypeOf (sender) Is ComboBox Then
        Dim cboThisCombobox = DirectCast(sender, ComboBox)

        RemoveHandler cboThisCombobox.SelectedValueChanged, LastEventHandler
    End If

End Sub
Wes
  • 371
  • 3
  • 18
0

CKRet/Quintin , thank you for the fast responses.

A quick try with this code seems better and breakpointing and stepping through the code seems to be firing the events correctly. I'm fairly new to .NET as the last real VB programming I did was VB6 so I'm not sure if this is the most elegant way to solve the problem.

Also a note that when LastEventHandler = Nothing, calling the RemoveHandler does not throw an exception, which is quite nice.

Maybe I should suggest to MS they should update that article.

Private Sub DGUserBets_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DGUserBets.EditingControlShowing

    Dim combo As ComboBox = CType(e.Control, ComboBox)

    Static LastEventHandler As EventHandler

    If (combo IsNot Nothing) Then

        // Remove an existing event-handler, if present, to avoid 
        // adding multiple handlers when the editing control is reused.
        RemoveHandler combo.SelectedIndexChanged, _
            LastEventHandler

        LastEventHandler = New EventHandler(AddressOf DGUBStake_SelectedIndexChanged)

        // Add the event handler. 
        AddHandler combo.SelectedIndexChanged, _
            LastEventHandler

    End If


End Sub
user57087
  • 147
  • 2
  • 4
  • 9
0

Simpler code which also appears to work well, as suggested by CKRet:

    Dim combo As ComboBox = CType(e.Control, ComboBox)

    If (combo IsNot Nothing) Then

       RemoveHandler combo.SelectedIndexChanged, AddressOf DGUBStake_SelectedIndexChanged

       AddHandler combo.SelectedIndexChanged, AddressOf DGUBStake_SelectedIndexChanged

    End If
user57087
  • 147
  • 2
  • 4
  • 9