开发者

Cannot remove rows in datagridview in vb.net

My datagridview is bound to a data table. I want to filter the datagridview without affecting data table. 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. I can see that it does execute rows removal in datagridview. But the problem is that when datagridview is shown on the form, it is unchanged, the same as the data table. I do not understand why rows are not removed on 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 Whi开发者_如何学运维le
                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. 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).

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.

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)

Oh wait... what about if you pass the datagridview by value instead of reference, so your changes at remove will be maintained?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜