просмотр через просмотр списка и доступ к подпунктам? - PullRequest
20 голосов
/ 05 апреля 2011

Мне трудно использовать оператор 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.

Ответы [ 4 ]

49 голосов
/ 05 апреля 2011

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

foreach(ListViewItem item in listView.Items){

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

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

4 голосов
/ 05 апреля 2011

Вам необходимо указать тип, если элемент в коллекции явно. Ключевое слово 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.

2 голосов
/ 05 апреля 2011

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

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

0 голосов
/ 05 апреля 2011

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

using System.Linq;

foreach(var item in listView.Items.Cast<ListViewItem>()){
    item.BackColor = ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...