2011-04-05 74 views
17

我在用WinForm ListView控件使用foreach语句时遇到了困难。以下两个代码块演示了我正在尝试做的事情。它与for循环一起工作,但不是foreach。通过列表查看和访问子项目?

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

VS

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

我尝试使用foreach循环,所以我可以更容易地删除ListView的项目。

回答

43

您需要指定类型:

foreach(ListViewItem item in listView.Items){ 

为了回答您的评论:

这是因为大多数控件的项集合实施非通用ICollection(和IEnumerable),见this MSDN entryListViewItemCollection例如。由于它没有实现通用ICollection<T>IEnumerable<T>,编译器无法通过查看集合本身来猜测项目的类型,所以您必须告诉它它们是ListViewItem而不是使用var

+0

为什么在这种情况下var不能满足要求? – sooprise 2011-04-05 14:18:25

+0

什么其他情况是不够的? – sooprise 2011-04-05 14:18:49

+0

Items集合类型是Object。这就是为什么推理将var后面的变量作为Object来执行的原因。如果您手动添加它们,ListView Items可以是ListViewItem的集合,也可以是使用DataSource的自己对象的集合。 – Larry 2011-04-05 14:30:41

0

使用LINQ

using System.Linq; 

foreach(var item in listView.Items.Cast<ListViewItem>()){ 
    item.BackColor = ... 
} 
+1

BoltClock的答案似乎更清晰。哪种方法更受欢迎,还是更符合行业标准? – sooprise 2011-04-05 14:20:33

+0

@sooprise:使用@ BoltClock的版本; 'Cast ()'对于查询组合非常有用,但这里只是一些不必要的开销和冗长。 – 2011-04-05 14:24:45

+0

是的,虽然LINQ *可以*做到这一点,它可能不是有意的。 – BoltClock 2011-04-05 14:30:26

2

的美丽的收集施法者你需要有该项目的类型 - 在这种情况下:ListViewItem。另外,如果您打算从集合中删除项目并使用foreach循环,则无法直接从循环中删除 - 您需要将每个项目添加到新集合中并在循环结束后从原始中删除该集合中的所有项目。

+0

我可能会回头使用for并向后迭代。感谢这些信息。 – sooprise 2011-04-05 14:27:23

4

您需要明确指定集合中项目的类型。关键字var使用类型推断来确定变量的类型。在foreach子句中的var的情况下,它使用IEnumerable的特定实现来确定类型。

  • 如果集合只实现IEnumerable(而不是一般的IEnumerable<T>),然后varobject
  • 如果集合实现一个通用IEnumerable<T>(比如,IEnumerable<int>),然后varT(在本例在这里,varint

在你的情况,ListViewItemCollection没有实现的任何一般形式,因此假设varobject。但是,如果枚举仅实现IEnumerable,编译器将允许您为迭代器变量指定更具体的类型,并自动将转换插入到该特定类型。

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

List<object> foo = new List<object>(); 

foo.Add("bar"); 
foo.Add(1); 

foreach(string bar in foo) 
{ 

} 

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