2008-12-19 9 views
17

Je reçois l'erreur ci-dessous lorsque vous essayez de boucle à travers une zone de liste, puis supprimer l'élément.Comment faire une boucle sur les éléments d'une zone de liste, puis supprimer ces éléments?

que cette liste recenseur est lié à a été modifié. Un énumérateur ne peut être utilisé que si la liste ne change pas.

foreach (string s in listBox1.Items) 
{ 
    MessageBox.Show(s); 
    //do stuff with (s); 
    listBox1.Items.Remove(s); 
} 

Comment puis-je supprimer l'élément et encore en boucle le contenu?

Répondre

35

Voulez-vous supprimer tous les éléments? Si oui, les foreach d'abord, puis il suffit d'utiliser Items.Clear() pour enlever tous par la suite.

Sinon, peut-être en boucle arrière par indexeur:

listBox1.BeginUpdate(); 
try { 
    for(int i = listBox1.Items.Count - 1; i >= 0 ; i--) { 
    // do with listBox1.Items[i] 

    listBox1.Items.RemoveAt(i); 
    } 
} finally { 
    listBox1.EndUpdate(); 
} 
+0

Je ** amour ** de savoir ce que downvote est sur le point !! –

+0

Moi aussi Marc. +1 pour contrer agir l'injustice de celui-ci. –

+0

Je serais ravi de connaître la raison des downvotes.Pour moi et pour vous! +1 –

1

Vous devez passer par la collection du dernier élément à la première. ce code est en vb

for i as integer= list.items.count-1 to 0 step -1 
.... 
list.items.removeat(i) 
next 
1

Jefferson est juste, vous devez le faire en arrière.

est ici le C# équivalent:

for (var i == list.Items.Count - 1; i >= 0; i--) 
{ 
    list.Items.RemoveAt(i); 
} 
+0

Nous savons déjà tout cela! Pourquoi te répéter? – Fandango68

+0

@ Fernando68 Parce que en 2008, il y avait des gens qui ne peuvent pas traduire de VB à C#: D –

23

Tout le monde a affiché « marche arrière » réponse, donc je vais donner l'alternative: créer une liste d'éléments que vous souhaitez supprimer, puis les retirer à la fin :

List<string> removals = new List<string>(); 
foreach (string s in listBox1.Items) 
{ 
    MessageBox.Show(s); 
    //do stuff with (s); 
    removals.Add(s); 
} 

foreach (string s in removals) 
{ 
    listBox1.Items.Remove(s); 
} 

parfois, le « travail arrière » est la meilleure méthode, parfois ce qui précède est mieux - surtout si vous avez affaire à un type qui a une méthode RemoveAll(collection). Il vaut la peine de savoir les deux.

+2

-1. listBox1.Items peut contenir des objets autres que string, dans ce cas InvalidCastException sera levée. –

+8

Si tel était le cas, la boucle foreach dans l'exemple de code dans la question aurait déjà explosé. Je faisais la même hypothèse que la question, ce que je trouve très raisonnable. –

+1

Oui, je l'ai remarqué. Il était amusant de vous downvote pour une raison pendant quelques minutes;) –

11

Voici ma solution sans aller en arrière et sans une liste temporaire

while (listBox1.Items.Count > 0) 
{ 
    string s = listBox1.Items[0] as string; 
    // do something with s 
    listBox1.Items.RemoveAt(0); 
} 
+0

+1 C'est juste! – Edyn

+1

@ Fernando68 comme le nombre de ListBox diminue à chaque fois qu'un élément est supprimé, la condition while finira par assimiler à false et la boucle se terminera. –

1

Que diriez-vous:

foreach(var s in listBox1.Items.ToArray()) 
{ 
    MessageBox.Show(s); 
    //do stuff with (s); 
    listBox1.Items.Remove(s); 
} 

Le ToArray fait une copie de la liste, de sorte que vous n'avez pas à vous soucier de il change la liste pendant que vous la traitez.

0

Vous ne pouvez pas faire de la modification à la collecte étant réitérée dans le bloc foreach.

Une solution rapide est de itérer sur une copie de la collection. Un moyen facile de faire cette copie est à travers le constructeur ArrayList. Les objets DataRowView de la collection copiée se réfèrent aux mêmes données sous-jacentes que votre code et peuvent être modifiés.

For Each item As DataRowView In New System.Collections.ArrayList(lbOrdersNeedToBeVoided.Items) 

s'il vous plaît lire http://social.msdn.microsoft.com/Forums/en-AU/vbgeneral/thread/b4d1f649-d78a-4e5b-8ad8-1940e3379bed

1

while(listbox.Items.Remove(s)) ; devrait fonctionner, aussi bien. Cependant, je pense que la solution inverse est le le plus rapide.

Questions connexes