【问题标题】:VB.NET Filtering ListItems ProblemVB.NET 过滤 ListItems 问题
【发布时间】:2009-07-22 15:02:26
【问题描述】:

我正在尝试根据字符串的存在来过滤 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

这显然是一个禁忌,因为它会产生错误:Collection was modified;枚举操作可能无法执行。

我也试过了:

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

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

非常感谢任何帮助。

【问题讨论】:

    标签: vb.net


    【解决方案1】:

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

    第一种方法会导致问题,因为您在迭代列表时正在修改列表。正如你所说,这是一个很大的禁忌。

    【讨论】:

    • 是的,这就是这样做的方法,但不幸的是仍然会导致 Collection was modified 错误。为您的帮助 +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 有 2 个列表

    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

    在这个 sn-p 中,我过滤 IndexOf = -1 而不是 > -1 以保留我想要的而不是过滤我不想要的。

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

    【讨论】:

    • +1 供您洞察。不幸的是,我没有 LINQ,因为这是 .NET 1.1,但仍然很高兴知道。
    • 有什么值得期待的:)
    【解决方案3】:

    根据上面 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
    

    【讨论】:

    • 这不是多余的两次通过吗?如果您无论如何都要循环通过它,那么您不妨一次性完成所有操作。单独的第二个循环,没有布尔检查,就足够了。
    • 其实我的代码是正确的。如果有一个不包含“W”的 ListItem,我只会过滤掉带有“W”的 ListItem。无论是否存在非 W ListItem,我的第二个循环都将摆脱所有“W”ListItem。再次更新示例。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      假设过滤字符串是一个文本框字符串,并且您想根据文本框中更改的文本过滤您的列表框。让文本框的名称为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
      

      这将过滤 listbox1 中的项目,就像您将在 TB_Filter 中键入一样。这会将您的项目的开头与您在 TB_Filter 中的过滤词相匹配。

      通过稍作改动(即,您可以使用contains 属性代替substring)来检查过滤器查询是否包含在项目中。

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

      【讨论】:

        猜你喜欢
        • 2012-09-15
        • 1970-01-01
        • 2022-10-14
        • 2016-10-18
        • 2012-03-16
        • 2021-10-09
        • 2011-05-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多