简体   繁体   English

无法删除 vb.net 中 datagridview 中的行

[英]Cannot remove rows in datagridview in vb.net

My datagridview is bound to a data table.我的 datagridview 绑定到数据表。 I want to filter the datagridview without affecting data table.我想在不影响数据表的情况下过滤 datagridview。 I know one way is to use bindingsource, but binding source will use column names in its filter.我知道一种方法是使用绑定源,但绑定源将在其过滤器中使用列名。 But I want to enable users to enter any string in a textbox to filter.但我想让用户在文本框中输入任何字符串进行过滤。 So I pass datagridview by reference to a function PassFilter which removes unwanted rows in datagridview.所以我通过引用 function PassFilter 来传递 datagridview,它删除了 datagridview 中不需要的行。 I can see that it does execute rows removal in datagridview.我可以看到它确实在 datagridview 中执行了行删除。 But the problem is that when datagridview is shown on the form, it is unchanged, the same as the data table.但是问题是datagridview在form上显示的时候是没有变化的,和数据表一样。 I do not understand why rows are not removed on datagridview我不明白为什么在 datagridview 上没有删除行

The code is as follows:代码如下:

DataGridView1.DataSource = table

PassFilter(DataGridView1, m_FilterQuick.strFilter.ToLower())
Private Sub PassFilter(ByRef datagridview As DataGridView, ByVal strFilter As String)
    Dim i As Integer = 0
    Dim j As Integer = 0
    Dim containStr As Boolean = False

    While i < datagridview.Rows.Count
        j = 0
        containStr = False
        'If all cells in a row does not contain strFilter, delete this row from datagridview
        While j < datagridview.Rows(i).Cells.Count
            Dim c As DataGridViewCell = datagridview.Rows(i).Cells(j)
            If Not c.Value Is DBNull.Value Or Nothing Then
                If c.Value.ToString().ToLower().Contains(strFilter) Then
                    containStr = True
                    Exit While
                End If

            End If
            j = j + 1
        End While
        If Not containStr Then
            datagridview.Rows.RemoveAt(i)
        End If
        i = i + 1
    End While

End Sub

Your big problem is that you're removing items in the DataGridViewRowCollection as you're iterating through that collection.您的大问题是您在遍历该集合时删除了 DataGridViewRowCollection 中的项目。 Even if you're not getting an 'index out of range' error doing this you're going to end up removing the wrong row(s) as the index value of later rows change when you remove earlier rows.即使您没有收到“索引超出范围”错误,您最终也会删除错误的行,因为当您删除较早的行时,后面的行的索引值会发生变化。

What you should do is instead of removing rows in your row loop, add the row's index to a List(Of Integers) .您应该做的不是删除行循环中的行,而是将行的索引添加到List(Of Integers)

After you're done iterating through all the rows in your DataGridView, Reverse() your list and use the row index values in your List to remove rows via the RemoveAt() method.完成对 DataGridView 中的所有行的迭代后, Reverse()列表并使用List中的行索引值通过RemoveAt()方法删除行。

Here's what I mean:这就是我的意思:

Private Sub PassFilter(ByRef datagridview As DataGridView, ByVal strFilter As String)
    Dim i As Integer = 0
    Dim j As Integer = 0
    Dim containStr As Boolean = False
    ' Row indexes we'll remove later on.
    Dim deleteIndexList As List(Of Integer) = New List(Of Integer)

    While i < datagridview.Rows.Count
        j = 0
        containStr = False
        'If all cells in a row does not contain strFilter, delete this row from datagridview 
        While j < datagridview.Rows(i).Cells.Count
            Dim c As DataGridViewCell = datagridview.Rows(i).Cells(j)
            ' Note: you'll want to enclose the tests for DBNull.Value and Nothing in parens like I show here.
            If Not (c.Value Is DBNull.Value And c.Value Is Nothing) Then
                If c.Value.ToString().ToLower().Contains(strFilter) Then
                    containStr = True
                    Exit While
                End If

            End If
            j = j + 1
        End While
        If Not containStr Then
            ' Don't remove rows here or your row indexes will get out of whack!
            ' datagridview.Rows.RemoveAt(i)
            deleteIndexList.Add(i)
        End If
        i = i + 1
    End While

    ' Remove rows by reversed row index order (highest removed first) to keep the indexes in whack.
    deleteIndexList.Reverse()
    For Each idx As Integer In deleteIndexList
        datagridview.Rows.RemoveAt(idx)
    Next
End Sub

Are you displaying the data as read-only, or for edit?您是将数据显示为只读还是用于编辑?

If you're allowing the users to edit, can you find some way to hide the rows you don't want shown, rather than trying to remove them?如果您允许用户进行编辑,您能否找到某种方法来隐藏您不想显示的行,而不是尝试删除它们?

If you're displaying this as read-only, you could grab the data after the filtering, and throw it into a new datagridview.... (ugly, yes, but a possible option)如果您将其显示为只读,则可以在过滤后获取数据,并将其放入新的 datagridview ....(丑陋,是的,但可能的选项)

Oh wait... what about if you pass the datagridview by value instead of reference, so your changes at remove will be maintained?哦等等...如果您通过值而不是引用传递 datagridview,那么您在删除时的更改将保持不变?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM