0

我有一个 vb.net 形式的 DataGridView,没有连接到任何源。当用户传递到另一行或关注 DGV 时,我想删除一行。如果其中有一个空单元格,则应删除该行。

那是我的代码:

Private Sub dgvSpSettings_RowLeave(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvSpSettings.RowLeave
    If e.RowIndex < (dgvSpSettings.Rows.Count - 1) Then 'Esclude l'ultima riga dal controllo sulle righe vuote
        If Me.dgvSpSettings.Rows(e.RowIndex).Cells(0).Value Is Nothing OrElse Me.dgvSpSettings.Rows(e.RowIndex).Cells(0).Value.ToString() = "" OrElse Me.dgvSpSettings.Rows(e.RowIndex).Cells(1).Value Is Nothing OrElse Me.dgvSpSettings.Rows(e.RowIndex).Cells(1).Value.ToString() = "" Then
            Me.dgvSpSettings.Rows.RemoveAt(e.RowIndex)
        End If
    End If
End Sub

这不起作用,因为我无法Me.dgvSpSettings.Rows.RemoveAt(e.RowIndex)在此事件中执行该方法。我试图将该行存储在一个私有变量中,然后在其他事件(如单击)中将其删除,但结果不是我所期望的。

有什么建议么?

4

4 回答 4

2

这可能不是最好的解决方案,但至少我想出了一些可能对你有用的东西。基本上,您将该行设置为只读而不是删除它。而且由于在您离开行时会调用paint,因此您可以将删除代码放入paint中。

Private Sub DataGridView1_RowLeave(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.RowLeave
    DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
    If e.RowIndex < (DataGridView1.Rows.Count - 1) Then
        If Me.DataGridView1.Rows(e.RowIndex).Cells(0).Value Is Nothing OrElse _
            Me.DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = "" OrElse _
            Me.DataGridView1.Rows(e.RowIndex).Cells(1).Value Is Nothing OrElse _
            Me.DataGridView1.Rows(e.RowIndex).Cells(1).Value.ToString() = "" Then
            Me.DataGridView1.Rows(e.RowIndex).ReadOnly = True
        End If
    End If
End Sub

Private Sub DataGridView1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles DataGridView1.Paint
    Dim i As Integer = 0
    While i <> DataGridView1.Rows.Count - 1
        If DataGridView1.Rows(i).ReadOnly Then
            DataGridView1.Rows.RemoveAt(i)
            If i = DataGridView1.Rows.Count - 1 Then
                Exit While
            End If
        Else
            i += 1
        End If
    End While
End Sub
于 2012-10-12T14:20:29.677 回答
1

您不能删除 RowLeave 事件处理中的行,因为它“忙”。我有时应用的这种情况的解决方案是调用 application.Idle 事件(我不太喜欢它,因为它感觉很笨拙,但效果很好):

  Private Sub dgvSpSettings_RowLeave(sender As Object, e As DataGridViewCellEventArgs) Handles dgvSpSettings.RowLeave
    Dim row As DataGridViewRow = dgvSpSettings.Rows(e.RowIndex)
    If Me.dgvSpSettings.Rows(e.RowIndex).Cells(0).Value Is Nothing OrElse
      e.dgvSpSettings.Rows(e.RowIndex).Cells(0).Value.ToString() = "" OrElse   
      Me.dgvSpSettings.Rows(e.RowIndex).Cells(1).Value Is Nothing OrElse 
      Me.dgvSpSettings.Rows(e.RowIndex).Cells(1).Value.ToString() = "" Then

      Me._rowToDelete = row
      AddHandler Application.Idle, AddressOf AppIdle
    End If
  End Sub

  Private _rowToDelete As DataGridViewRow

  Private Sub AppIdle(sender As Object, e As EventArgs)
    If Me._rowToDelete IsNot Nothing Then
      dgvSpSettings.Rows.Remove(Me._rowToDelete)
      Me._rowToDelete = Nothing
    End If
    RemoveHandler Application.Idle, AddressOf AppIdle
  End Sub
于 2012-10-13T11:09:53.673 回答
0

这是我的最终解决方案。它对我有用,我希望它在概念上是正确的。我使用了代表和Leave + LostFocus事件。

'**********
'* Controllo righe da eliminare
'**********
Private Sub dgvSpSettings_RowLeave(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvSpSettings.RowLeave
    Me.dgvSpSettings.CommitEdit(0)

    Dim row As DataGridViewRow = Me.dgvSpSettings.Rows(e.RowIndex)

    For Each cell In row.Cells
        cell.Style.BackColor = Color.White
    Next

    If Not row.IsNewRow() Then 'Esclude l'ultima riga dal controllo sulle righe vuote
        If String.IsNullOrEmpty(row.Cells(0).Value) OrElse String.IsNullOrEmpty(row.Cells(1).Value) Then
            _rowBlank = row
        End If
    End If

End Sub

Private Delegate Sub setCurrentCellDelegate()

Private Sub setCurrentCell()
    For Each cell In _rowBlank.Cells
        cell.Style.BackColor = Color.LightSalmon
    Next

    Me.dgvSpSettings.CurrentCell = _rowBlank.Cells(0)
    Me.dgvSpSettings.BeginEdit(True)
    _rowBlank = Nothing
End Sub

Private Delegate Sub removeRowDelegate()

Private Sub removeRow()
    Me.dgvSpSettings.Rows.Remove(_rowBlank)
    _rowBlank = Nothing
    _rowBlankDeleting = False
End Sub

'**********
'* Controllo righe da eliminare
'**********
Private Sub dgvSpSettings_Leave(sender As Object, e As System.EventArgs) Handles dgvSpSettings.Leave
    If _rowBlank IsNot Nothing AndAlso _rowBlankDeleting = False Then
        If MsgBox("Alcuni campi della riga non sono stati valorizzati. Eliminare la riga?", vbYesNo + vbInformation, "Eliminare") = MsgBoxResult.Yes Then
            _rowBlankDeleting = True
            Me.dgvSpSettings.BeginInvoke(New removeRowDelegate(AddressOf removeRow))
        Else
            Me.dgvSpSettings.BeginInvoke(New setCurrentCellDelegate(AddressOf setCurrentCell))
        End If
    End If
End Sub

'**********
'* Controllo righe da eliminare
'**********
Private Sub dgvSpSettings_LostFocus(sender As Object, e As System.EventArgs) Handles dgvSpSettings.LostFocus
    If _rowBlank IsNot Nothing AndAlso _rowBlank IsNot Me.dgvSpSettings.CurrentRow AndAlso _rowBlankDeleting = False Then
        If MsgBox("Alcuni campi della riga non sono stati valorizzati. Eliminare la riga?", vbYesNo + vbInformation, "Eliminare") = MsgBoxResult.Yes Then
            _rowBlankDeleting = True
            Me.dgvSpSettings.BeginInvoke(New removeRowDelegate(AddressOf removeRow))
        Else
            Me.dgvSpSettings.BeginInvoke(New setCurrentCellDelegate(AddressOf setCurrentCell))
        End If
    End If
End Sub
于 2012-10-15T07:42:43.237 回答
0

实际上问题是你不能从下往上删除(1、2、3等),你必须像这样从上到下(3、2、1):

For j = DataGrid1.Rows.Count - 2 To 0 Step -1
   DataGrid1.Rows.RemoveAt(j)
Next

问题是VB认为第一行是不包含任何数据的行(你可以输入信息的空行)。这对我有用。

于 2014-06-26T03:12:44.217 回答