VB.NET过滤ListItems问题

时间:2009-07-22 15:02:27

标签: vb.net

我正在尝试根据字符串的存在过滤ListBox。基本上,如果有一个ListItem不包含该字符串,那么我想删除所有包含该字符串的ListItem。这是我尝试过的:

Dim Item As ListItem
For Each Item In CtheList.Items
    If Item.Text.IndexOf("W:") = -1 Then
        CtheList.Items.Remove(Item)
     End If
 Next

这显然是禁忌,因为它会产生错误:收集被修改;枚举操作可能无法执行。

我也尝试过:

Dim Item As ListItem
For Each Item In CtheList.Items
    If Item.Text.IndexOf("W:") = -1 Then
        Dim i As Integer
        For i = 0 To CtheList.Items.Count - 1
            If CtheList.Items.Item(i).Text.IndexOf("W:") > -1 Then
                CtheList.Items.RemoveAt(i)
            End If
        Next i
    End If
Next

这会生成超出范围异常的索引。

非常感谢任何帮助。

5 个答案:

答案 0 :(得分:3)

尝试反转循环,即从列表末尾开始。这样,删除项目不会改变您仍需要检查的剩余项目的索引(这是您超出范围异常的原因)。

第一种方式会导致问题,因为您在迭代时修改列表。就像你说的那样,这是一个很大的禁忌。

答案 1 :(得分:2)

从列表中删除项目时,有几个选项。正如您所发现的那样,在foreach循环中修改集合是行不通的。倒计时的for循环是@balpha提到的答案。

另一种选择是将项目列表存储在单独的列表中,然后对其进行迭代以从原始列表中删除项目。另一种选择是使用LINQ。

示例清单:

Dim stringList As New List(Of String)
stringList.Add("W:foo")
stringList.Add("bar")
stringList.Add("barW:")
stringList.Add("foo")

反向循环

For i As Integer = stringList.Count - 1 To 0 Step -1
    If stringList(i).IndexOf("W:") > -1 Then stringList.RemoveAt(i)
Next

ForEach with 2 Lists

Dim removeList As New List(Of String)
' store items to remove here
For Each s As String In stringList
    If s.IndexOf("W:") > -1 Then removeList.Add(s)
Next
' remove stored items here
For Each s As String In removeList
    stringList.Remove(s)
Next

<强> LINQ

在此代码段中,我对IndexOf = -1进行过滤,而不是&gt; -1保持我想要的东西而不是过滤我不想要的东西。

stringList = stringList.Where(Function(s) s.IndexOf("W:") = -1).ToList()

答案 2 :(得分:1)

根据上面的balpha的帮助,这就是我最终做的事情:

Dim StringPresent As Boolean = False
Dim Item As ListItem

For Each Item In CtheList.Items
    If Item.Text.IndexOf("W:") = -1 Then
        StringPresent = True
        Exit For
    End If
Next

If StringPresent = True Then
    Dim i As Integer
    For i = CtheList.Items.Count - 1 To 0 Step -1
        If CtheList.Items.Item(i).Text.IndexOf("W:") > -1 Then
            CtheList.Items.RemoveAt(i)
        End If
    Next i
End If

答案 3 :(得分:0)

为什么不在将项目放入列表框之前对其进行过滤?

答案 4 :(得分:0)

假设过滤字符串是文本框字符串,并且您希望根据文本框中更改的文本过滤列表框。让文本框的名称为TB_Filter

Public Class Form1之后,从代码顶部放置此行代码,暂时保留您的列表框项目。

Dim TempHoldMyItems As New ArrayList

现在在form_load事件中使用这段代码来更新列表框项目中的临时列表。

TempHoldMyItems.Clear()
TempHoldMyItems.AddRange(listbox1.Items)

好的,现在您可以根据TB_Filter中的文本过滤列表框项目。在TB_Filter Text Changed事件中使用此代码。

listbox1.Items.Clear()
For Each item As String In TempHoldMyItems
    If item.Length >= TB_Filter.Text.Length Then
        If item.Substring(0, TB_Filter.Text.Length) = TB_SearchInSelected.Text Then
            listbox1.Items.Add(item)
        End If
    End If
Next

这将过滤您在TB_Filter中输入的listbox1中的项目。这会将您的商品的开头与TB_Filter中的过滤字匹配。

通过进行少量更改(即代替substring,您可以使用contains属性)来检查过滤查询是否包含在项目中。

listbox1.Items.Clear()
For Each item As String In TempHoldMyItems
    If item.Contains(TB_Filter.Text) Then
        listbox1.Items.Add(item)
    End If
Next