2011-04-05 18 views
17

Tengo dificultades para usar una instrucción foreach con un control ListView de WinForm. Los siguientes dos bloques de código demuestran lo que intento hacer. Funciona con un ciclo for, pero no un foreach.foreach-ing a través de una vista de lista y accediendo a subtemas?

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

vs

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

Estoy intentando utilizar un bucle foreach para que pueda eliminar más fácilmente los elementos de la ListView.

Respuesta

43

es necesario especificar el tipo:

foreach(ListViewItem item in listView.Items){ 

Para responder a sus comentarios:

Esto se debe a colecciones artículo más controles se implementan el no genérico ICollection (y IEnumerable), ver this MSDN entry para ListViewItemCollection por ejemplo. Dado que no implementa el genérico ICollection<T> o IEnumerable<T>, el compilador no puede adivinar el tipo de elementos para que no miren las colecciones, por lo que debe decir que son del tipo ListViewItem en lugar de usar var.

+0

¿Por qué var no será suficiente en esta situación? – sooprise

+0

¿Qué otras situaciones es var no suficiente? – sooprise

+0

El tipo de colección de elementos es Object. Es por eso que la inferencia hace que la variable detrás de var también sea un Objeto. Los elementos de la vista de lista pueden ser una colección de ListViewItem si los agrega manualmente o una colección de sus propios objetos si usa DataSource. – Larry

0

Utilice la hermosa máquina de colada colección de LINQ

using System.Linq; 

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

La respuesta de BoltClock parece más limpia. ¿Qué método es el preferido o más estándar de la industria? – sooprise

+0

@sooprise: Usa la versión de @ BoltClock; 'Cast ()' es útil para la composición de consultas, pero aquí solo se necesita un poco de sobrecarga y de detalle. –

+0

Sí, aunque LINQ * puede * hacer esto, probablemente no sea así. – BoltClock

2

Usted necesita tener el tipo de la partida - en este caso: ListViewItem.

Además, si está planeando eliminar elementos de la colección y está utilizando un bucle foreach, no puede eliminarlo directamente del bucle. Debería agregar cada elemento para eliminarlo de una nueva colección y elimine todos los elementos en esa colección del original después de la terminación del ciclo.

+0

Podría volver a utilizar un para e iterar hacia atrás. Gracias por esta información. – sooprise

4

Debe especificar el tipo si el elemento en la colección explícitamente. La palabra clave var utiliza la inferencia de tipo para determinar el tipo de la variable. En el caso de var en una cláusula foreach, utiliza la implementación particular de IEnumerable para determinar el tipo.

  • Si la colección sólo implementa IEnumerable (y no un genérico IEnumerable<T>), entonces var habrá object
  • Si la colección implementa genérico IEnumerable<T> (por ejemplo, IEnumerable<int>), entonces var habrá T (en el ejemplo aquí, var habría int)

En su caso, ListViewItemCollection no implementa ninguna forma genérica de IEnumerable<T>, por lo que var se supone que es object. Sin embargo, el compilador le permitirá especificar un tipo más específico para la variable del iterador si el enumerable solo implementa IEnumerable, e inserta automáticamente un molde para ese tipo en particular.

Tenga en cuenta que, dado que hay un operador de conversión, la conversión fallará en el tiempo de ejecución si el objeto no es de ese tipo en particular.Por ejemplo, yo puedo hacer esto:

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

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

foreach(string bar in foo) 
{ 

} 

Esto es legal, pero fallará cuando el iterador alcanza el segundo punto, ya que no es un string.

Cuestiones relacionadas