web-dev-qa-db-ja.com

リストビューを介してforeachingし、サブアイテムにアクセスしますか?

WinForm ListViewコントロールでforeachステートメントを使用するのに問題があります。次の2つのコードブロックは、私がやろうとしていることを示しています。これは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
}

ListViewから項目をより簡単に削除できるように、foreachループを使用しようとしています。

22
sooprise

タイプを指定する必要があります:

foreach(ListViewItem item in listView.Items){

あなたのコメントに答えるには:

これは、ほとんどのコントロールのアイテムコレクションが非ジェネリックICollection(およびIEnumerable)を実装しているためです。たとえば、ListViewItemCollectionの-​​ このMSDNエントリ を参照してください。汎用のICollection<T>またはIEnumerable<T>を実装していないため、コンパイラーはコレクション自体を見てアイテムのタイプを推測できないため、コレクションのタイプであることを通知する必要がありますListViewItemを使用する代わりにvar

51
BoltClock

コレクション内のアイテムのタイプを明示的に指定する必要があります。 varキーワードは、変数の型を判別するために型推論を使用します。 var句のforeachの場合は、IEnumerableの特定の実装を使用してタイプを判別します。

  • コレクションがIEnumerableだけを実装している場合(ジェネリックIEnumerable<T>ではない)、varobjectになります。
  • コレクションが1つのジェネリックIEnumerable<T>(たとえば、IEnumerable<int>)を実装する場合、varTになります(この例では、varint

あなたの場合、ListViewItemCollectionIEnumerable<T>の一般的な形式を実装していないため、varobjectであると見なされます。ただし、列挙型がIEnumerableのみを実装し、その特定の型へのキャストを自動的に挿入する場合、コンパイラーはイテレーター変数のより具体的な型を指定できます。

キャスト演算子があるため、オブジェクトがその特定のタイプでない場合、実行時にキャストが失敗することに注意してください。たとえば、私はこれを行うことができます:

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

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

foreach(string bar in foo)
{

}

これは正当ですが、stringではないため、イテレータが2番目のアイテムに到達すると失敗します。

4
Adam Robinson

アイテムのタイプ(この場合はListViewItem)が必要です。

また、コレクションからアイテムを削除する予定で、foreachループを使用している場合は、ループしているから直接削除することはできません。削除する各アイテムを新しいコレクションに追加して、すべてのアイテムを削除する必要があります。ループの終了後、元のコレクションから。

2
T.K.

LINQの美しいコレクションキャスターを使用する

using System.Linq;

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