it-swarm.com.ru

просмотр через просмотр списка и доступ к подпунктам?

У меня возникают трудности с использованием оператора foreach с элементом управления WinForm ListView. Следующие два блока кода демонстрируют то, что я пытаюсь сделать. Работает с циклом 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.

19
sooprise

Вам необходимо указать тип:

foreach(ListViewItem item in listView.Items){

Чтобы ответить на ваши комментарии:

Это связано с тем, что в большинстве коллекций элементов управления реализованы неуниверсальные ICollectionIEnumerable), см., Например, эту запись MSDN для ListViewItemCollection. Поскольку он не реализует универсальный ICollection<T> или IEnumerable<T>, компилятор не может угадать тип элементов по просмотру самих коллекций, поэтому вы должны сказать ему, что они имеют тип ListViewItem вместо использования var.

47
BoltClock

Вам необходимо указать тип, если элемент в коллекции явно. Ключевое слово var использует определение типа для определения типа переменной. В случае var в предложении foreach он использует конкретную реализацию IEnumerable для определения типа.

  • Если коллекция реализует только IEnumerable (а не универсальный IEnumerable<T>), тогда var будет object
  • Если в коллекции реализован один общий IEnumerable<T> (скажем, IEnumerable<int>), то var будет T (в приведенном здесь примере var будет int)

В вашем случае ListViewItemCollection не реализует никакой общей формы IEnumerable<T>, поэтому предполагается, что varobject. Тем не менее, компилятор позволит вам указать более конкретный тип для переменной итератора, если перечисляемый реализует только IEnumerable, и он автоматически вставляет приведение к этому конкретному типу.

Обратите внимание, что, поскольку есть оператор приведения, приведение не будет выполнено во время выполнения, если объект не относится к этому конкретному типу. Например, я могу сделать это:

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

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

foreach(string bar in foo)
{

}

Это допустимо, но завершится неудачно, когда итератор достигнет второго элемента, поскольку он не является string.

4
Adam Robinson

У вас должен быть тип элемента - в этом случае: ListViewItem.

Кроме того, если вы планируете удалять элементы из коллекции и используете цикл foreach, вы не можете напрямую удалить из цикла, который вы просматриваете, - вам нужно добавить каждый элемент для удаления в новую коллекцию и удалить все элементы в этой коллекции от оригинала после окончания цикла.

2
T.K.

Используйте красивую коллекционную заклинатель LINQ

using System.Linq;

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