2011-04-05 90 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將失敗。