1

我在 VB.Net 2008 中有一个连接到 Access DB 表的 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 在适当的地方强制该行保存更改?我应该在哪里称呼它?

谢谢你。

4

5 回答 5

2

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

于 2009-02-24T17:22:57.880 回答
2

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

此外,我建议为分配和删除创建处理程序成员变量,因为它似乎比总是说 Remove New 和 Add New 更好。

于 2009-02-24T17:29:08.223 回答
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
于 2009-02-24T17:57:32.320 回答
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
于 2009-02-24T18:30:42.180 回答
0

我知道这是一篇过时的帖子,但是在解决同样的问题半天后,我找到了另一种方法来解决这个问题,所以我认为它值得分享。

添加第二个处理程序来处理组合框的离开事件,然后删除选择值更改的处理程序。看起来工作起来很流畅,并且与我发现的另一个选项不同,它给出了所需的结果操作(与在实际处理事件中删除值更改处理程序不同,如果您从同一个组合框中重新选择则不会触发)

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
于 2012-06-14T19:20:01.223 回答