Ваша большая проблема заключается в том, что вы удаляете элементы в DataGridViewRowCollection во время итерации по этой коллекции. Даже если вы не получите сообщение об ошибке «индекс вне диапазона», это приведет к удалению неправильных строк, так как значение индекса более поздних строк изменяется при удалении более ранних строк.
Что нужно сделать, вместо удаления строк в цикле строк, добавить индекс строки в List(Of Integers)
.
После того, как вы закончите итерацию по всем строкам в DataGridView, Reverse()
ваш список и используйте значения индекса строки в вашем List
для удаления строк с помощью метода RemoveAt()
.
Вот что я имею в виду:
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