EditingControlShowing事件多次触发

时间:2009-02-24 17:13:14

标签: vb.net visual-studio-2008 datagridview event-handling editcontrol

我在VB.Net 2008中有一个连接到Access数据库表的DGV。 DGV不是只读的,但除了包含组合框的列之外,其中包含只读列。组合框允许用户选择该特定行的结果,然后程序将预先计算的值复制到“利润”列中,具体取决于组合框中选择的项目。然后用户点击“保存”按钮并更新数据库(目前通过XSD中的SQL方法)。

到目前为止还很容易。

这是代码。

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

我遇到的问题是,如果用户从组合框中选择了所需的结果但是没有按Enter键,只需将鼠标移到另一个组合框上再次选择不同行的结果,第一个事件处理程序未断开连接,因此事件多次触发。这会导致各种默认的MsgBox错误,并在用户尝试提交对DB / exit程序等的所有更改时出现问题。

我需要做什么?我是否需要.EndEdit适当的地方强制行保存更改?我应该在哪里打个电话?

谢谢。

5 个答案:

答案 0 :(得分:2)

快速浏览代码会提出这个问题: 如果在删除现有的EventHandler时创建一个新的EventHandler它是同一个吗?

答案 1 :(得分:2)

我遇到了类似的问题,如果退出的单元格是您要查找的单元格(IE CellLeave),则为e.ColumnIndex = myEditableColumn.Index添加处理程序,然后调用gv.EndEdit()

此外,我建议将处理程序成员变量用于赋值和删除,因为它似乎更好,然后总是说删除新建和添加新。

答案 2 :(得分:0)

CKRet / Quintin,谢谢您的快速回复。

使用此代码进行快速尝试似乎更好,并且通过代码的断点和步进似乎正在正确地触发事件。我是.NET的新手,因为我做的最后一个真正的VB编程是VB6所以我不确定这是否是解决问题的最优雅的方法。

另请注意,当LastEventHandler = Nothing时,调用RemoveHandler不会抛出异常,这非常好。

也许我应该向MS建议他们应该更新那篇文章。

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

答案 3 :(得分:0)

更简单的代码,似乎也很有效,正如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

答案 4 :(得分:0)

我知道这是一个古老的帖子,但是在经历了半天的同样问题之后,我找到了另一种解决方法,所以我认为值得分享。

添加第二个处理程序来处理组合框的leave事件,然后删除selectedvalue的处理程序已更改。似乎工作相当光滑,不像我发现的另一个选项给出了所需的结果动作(不像在实际处理事件中删除值更改处理程序,如果从同一个组合框中重新选择则不会触发)

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