【问题标题】:foreach-ing through a listview and accessing subitems?通过列表视图进行 foreach 并访问子项?
【发布时间】:2011-07-30 00:36:57
【问题描述】:

我在使用带有 WinForm ListView 控件的 foreach 语句时遇到了困难。以下两个代码块演示了我正在尝试做的事情。它适用于 for 循环,但不适用于 foreach。

foreach(var item in listView.Items){
    item. <-Can't access any of the subitems of this item
}

for(int i=0;i<listView.Items.Count;i++){
    listView.Items[i].Subitems[1] <- Here I can access the sub items
}

我正在尝试使用 foreach 循环,以便更轻松地从 ListView 中删除项目。

【问题讨论】:

    标签: c# winforms listview foreach


    【解决方案1】:

    你需要指定类型:

    foreach(ListViewItem item in listView.Items){
    

    回答你的cmets:

    这是因为大多数控件的项目集合都实现了非泛型ICollection(和IEnumerable),例如this MSDN entry 中的ListViewItemCollection。由于它没有实现通用的ICollection&lt;T&gt;IEnumerable&lt;T&gt;,编译器无法通过查看集合本身来猜测项目的类型,因此您必须告诉它它们的类型是ListViewItem使用var

    【讨论】:

    • 为什么在这种情况下 var 不够用?
    • 还有哪些情况下var不够用?
    • Items 集合类型是 Object。这就是为什么将 var 后面的变量也作为 Object 进行推理的原因。如果您手动添加列表视图项,则可以是 ListViewItem 的集合,如果您使用 DataSource,则可以是您自己的对象的集合。
    • @BoltClock 使用forearch(ListViewDataItem item in listView.Items){ 不是更好吗?通过成为特定类型会更有效,对吧?
    • @DanielV:那是 ASP.NET ListView。这是 WinForms ListView,其 Items 属性是 ListViewItems 的非泛型集合(WinForms 中没有 ListViewDataItem)。
    【解决方案2】:

    如果集合中的项目显式,您需要指定类型。 var 关键字使用类型推断来确定变量的类型。对于varforeach 子句中的情况,它使用IEnumerable 的特定实现来确定类型。

    • 如果集合只实现IEnumerable(而不是通用的IEnumerable&lt;T&gt;),那么var将是object
    • 如果集合实现了一个通用的IEnumerable&lt;T&gt;(例如IEnumerable&lt;int&gt;),那么var 将是T(在此处的示例中,var 将是int

    在您的情况下,ListViewItemCollection 没有实现IEnumerable&lt;T&gt; 的任何通用形式,因此var 被假定为object。但是,如果可枚举仅实现 IEnumerable,编译器将允许您为迭代器变量指定更具体的类型,并且它会自动插入对该特定类型的强制转换。

    请注意,由于有一个转换运算符,如果对象不是该特定类型,则转换将在运行时失败。例如,我可以这样做:

    List<object> foo = new List<object>();
    
    foo.Add("bar");
    foo.Add(1);
    
    foreach(string bar in foo)
    {
    
    }
    

    这是合法的,但是当迭代器到达第二个项目时会失败,因为它不是string

    【讨论】:

      【解决方案3】:

      您需要知道项目的类型 - 在这种情况下:ListViewItem

      此外,如果您打算从集合中删除项目并使用 foreach 循环,则不能直接从循环中删除 - 您需要将要删除的每个项目添加到新集合中,并且循环终止后,从原始集合中删除该集合中的所有项目。

      【讨论】:

      • 我可能会回到使用 for 并向后迭代。感谢您提供此信息。
      【解决方案4】:

      使用漂亮的 LINQ 集合脚轮

      using System.Linq;
      
      foreach(var item in listView.Items.Cast<ListViewItem>()){
          item.BackColor = ...
      }
      

      【讨论】:

      • BoltClock 的答案似乎更清晰。哪种方法更受欢迎,或者更符合行业标准?
      • @sooprise:使用@BoltClock 的版本; Cast&lt;T&gt;() 对于查询组合很有用,但在这里只是有点不必要的开销和冗长。
      • 是的,虽然 LINQ 可以做到这一点,但它可能不打算这样做。
      猜你喜欢
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 2011-07-12
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 2012-06-13
      • 2020-08-23
      相关资源
      最近更新 更多