2008-12-19 14 views
17

Otrzymuję błąd poniżej, próbując przechodzić przez pole listy, a następnie usunąć element.Jak przepętlić elementy w polu listy, a następnie usunąć te elementy?

Lista, do której jest przypisany ten moduł wyliczający została zmodyfikowana. Modułu wyliczającego można używać tylko wtedy, gdy lista się nie zmienia.

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

Jak mogę usunąć pozycję i nadal pętlę poprzez zawartość?

Odpowiedz

35

Czy chcesz usunąć wszystkie przedmioty? Jeśli tak, najpierw wykonaj foreach, a następnie po prostu użyj Items.Clear(), aby usunąć wszystkie później.

przeciwnym razie może pętla tyłu przez indekser:

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

Chciałbym ** uwielbiam ** wiedzieć, o co chodzi w tym punkcie prasowym !! –

+0

Ja też Marc. +1 do walki z niesprawiedliwością. –

+0

Chciałbym poznać powód downvotes.Zarówno dla mnie, jak i dla ciebie! +1 –

1

Trzeba przejść przez kolekcji z ostatniej pozycji na pierwszą. ten kod jest w vb

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

Jefferson ma rację, trzeba to zrobić w tył.

Oto C# równoważne:

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

Już to wszystko wiemy! Po co się powtarzać? – Fandango68

+0

@ Fernando68 Ponieważ w 2008 roku byli ludzie, którzy nie mogą przetłumaczyć z VB na C#: D –

23

Wszyscy opublikował „cofa” odpowiedź, więc dam alternatywę: stworzyć listę elementów, które chcesz usunąć, a następnie usunąć je na końcu :

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); 
} 

czasami metoda „działa wstecz” jest lepsze, czasami powyżej jest lepiej - szczególnie jeśli masz do czynienia z typem, który posiada metodę RemoveAll(collection). Warto wiedzieć oboje.

+2

-1. ListBox1.Items może zawierać obiekty inne niż łańcuch znaków, w takim przypadku zostanie zgłoszony wyjątek InvalidCastException. –

+8

Jeśli tak było, pętla foreach w kodzie przykładowym w pytaniu już byłaby wysadzona w powietrze. Miałem takie samo założenie, jak pytanie, które uważam za całkiem rozsądne. –

+1

Tak, zauważyłem to. Fajnie było cię zgodzić z jakiegoś powodu;) –

11

Oto moje rozwiązanie bez przechodzenia do tyłu i bez czasowego listy

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

+1 To już wszystko! – Edyn

+1

@ Fernando68, ponieważ liczba elementów ListBox jest zmniejszana za każdym razem, gdy element jest usuwany, warunek while będzie w końcu równy false i pętla się zakończy. –

1

Jak o:

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

ToArray tworzy kopię listy, więc nie trzeba się martwić zmienia listę podczas jej przetwarzania.

0

Nie można dokonać modyfikacji kolekcji, która jest iterowana w bloku ForEach.

Szybką poprawką jest powtórzenie kopii kolekcji. Prostym sposobem na wykonanie tej kopii jest użycie konstruktora ArrayList. Obiekty DataRowView w skopiowanej kolekcji będą odnosić się i będą mogły modyfikować te same podstawowe dane, co Twój kod.

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

proszę przeczytać http://social.msdn.microsoft.com/Forums/en-AU/vbgeneral/thread/b4d1f649-d78a-4e5b-8ad8-1940e3379bed

1

while(listbox.Items.Remove(s)) ; powinny działać, jak również. Jednak myślę, że rozwiązaniem wstecznym jest najszybszy.

Powiązane problemy