EditingControlShowing eventos disparando várias vezes
-
06-09-2019 - |
Pergunta
Eu tenho um DGV em VB.Net 2008 conectado a uma tabela do Access DB. A DGV não é somente leitura, mas está cheio de colunas somente leitura com exceção de um, que contém uma caixa de combinação. A caixa de combinação permite que o usuário selecione um resultado para essa linha particular, e, em seguida, o programa copia em um valor pré calculado para a coluna "Lucro", dependendo do item selecionado na caixa de combinação. Em seguida, o usuário pressiona o botão Salvar e as atualizações DB (atualmente através de métodos SQL no XSD).
Fácil o suficiente até agora.
Aqui está o código.
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
O problema que tenho é que parece que se um usuário seleciona o resultado desejado na combobox mas NÃO pressione Enter, e simplesmente mouses sobre a uma caixa de combinação diferente para selecione novamente o resultado para uma linha diferente, o primeiro eventhandler não está desligado e, portanto, os eventos disparar várias vezes. Isso, então, faz com que vários erros padrão MsgBox e traz problemas quando o usuário tenta para confirmar todas as alterações ao programa DB / saída etc etc.
O que eu preciso fazer? Preciso .EndEdit algum lugar apropriado para forçar a linha para salvar as alterações? E onde eu deveria chamar isso?
Obrigado.
Solução
Um rápido olhar sobre o código traz à tona a pergunta: Se você criar um novo EventHandler ao remover o existente é o mesmo?
Outras dicas
Eu tive um problema semelhante, adicione um manipulador para CellLeave
se a célula a ser retirado é a célula que você está procurando (IE e.ColumnIndex = myEditableColumn.Index
), em seguida, chamar gv.EndEdit ()
Também eu recomendaria fazer as variáveis ??manipuladores membros para atribuição e remoção porque parece mais agradável, em seguida, sempre dizendo remover novo e adicionar novos.
CKRet / Quintin, obrigado pelas respostas rápidas.
A tentativa rápida com este código parece melhor e breakpointing e percorrendo o código parece estar disparando os eventos corretamente. Eu sou bastante novo para .NET como o último VB verdadeira programação que fiz foi VB6, então eu não tenho certeza se esta é a maneira mais elegante para resolver o problema.
Também uma nota que quando LastEventHandler = Nada, chamando a RemoveHandler não lançar uma exceção, que é bastante agradável.
Talvez eu deveria sugerir a MS devem atualizar este artigo.
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
código mais simples que também parece funcionar bem, como sugerido por 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
Eu sei que este é um posto arcaico, mas depois buggering ao redor com esse mesmo problema para metade de um dia eu encontrei uma maneira de resolver isso de outra forma, então eu pensei que seria vale a pena compartilhar.
A adição de um segundo manipulador para manipular o evento licença da caixa de combinação, que, em seguida, remove o manipulador de SelectedValue alterado. Parece funcionar bastante liso, e ao contrário de outra opção que eu encontrei dá a ação resultante desejada (ao contrário de remover o manipulador valor alterado no evento manipulação real que então não a incêndios, se você selecionar novamente a partir do mesmo 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