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

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

Ответы

Ответ 1

Вам нужно указать тип:

foreach(ListViewItem item in listView.Items){

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

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

Ответ 2

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

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

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

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

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

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

foreach(string bar in foo)
{

}

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

Ответ 3

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

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

Ответ 4

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

using System.Linq;

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