web-dev-qa-db-fra.com

rechercher dans une liste et accéder à des sous-éléments?

J'ai des difficultés à utiliser une instruction foreach avec un contrôle WinForm ListView. Les deux blocs de code suivants illustrent ce que j'essaie de faire. Cela fonctionne avec une boucle for, mais pas une foreach. 

foreach(var item in listView.Items){
    item. <-Can't access any of the subitems of this item
}

contre

for(int i=0;i<listView.Items.Count;i++){
    listView.Items[i].Subitems[1] <- Here I can access the sub items
}

J'essaie d'utiliser une boucle foreach afin de pouvoir supprimer plus facilement des éléments de ListView.

19
sooprise

Vous devez spécifier le type:

foreach(ListViewItem item in listView.Items){

Pour répondre à vos commentaires:

Cela est dû au fait que les collections d'éléments de la plupart des contrôles implémentent la variable ICollection (et IEnumerable) non générique, voir cette entrée MSDN pour ListViewItemCollection par exemple. Comme il n'implémente pas les ICollection<T> ou IEnumerable<T> génériques, le compilateur ne peut pas deviner le type des éléments en consultant les collections elles-mêmes; vous devez donc lui indiquer qu'ils sont de type ListViewItem au lieu d'utiliser var.

47
BoltClock

Vous devez spécifier le type si l'élément de la collection est explicitement. Le mot clé var utilise l'inférence de type afin de déterminer le type de la variable. Dans le cas de var dans une clause foreach, il utilise l'implémentation particulière de IEnumerable pour déterminer le type.

  • Si la collection implémente uniquement IEnumerable (et non un IEnumerable<T> générique), alors var sera object
  • Si la collection implémente un IEnumerable<T> générique (par exemple, IEnumerable<int>), alors var sera T (dans l'exemple ici, var serait int)

Dans votre cas, ListViewItemCollection n'implémente aucune forme générique de IEnumerable<T>, donc var est supposé être object. Cependant, le compilateur vous permettra de spécifier un type plus spécifique pour la variable itérateur si l'énumérable n'implémente que IEnumerable et insère automatiquement une conversion dans ce type particulier.

Notez que, du fait qu’il existe un opérateur de transtypage, la conversion échouera au moment de l'exécution si l'objet n'est pas de ce type particulier. Par exemple, je peux faire ceci:

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

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

foreach(string bar in foo)
{

}

Ceci est légal, mais échouera lorsque l'itérateur atteindra le second élément, puisqu'il ne s'agit pas d'une string.

4
Adam Robinson

Vous devez avoir le type d'élément - dans ce cas: ListViewItem.

De même, si vous envisagez de supprimer des éléments de la collection et que vous utilisez une boucle foreach, vous ne pouvez pas supprimer directement de la boucle en cours; vous devez ajouter chaque élément à supprimer dans une nouvelle collection et supprimer tous les éléments. dans cette collection de l'original après la fin de la boucle.

2
T.K.

Utilisez la belle collection de roulettes de LINQ

using System.Linq;

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