2012-10-31 19 views
16

Chcę to zrobić, ale listbox zmienia się przy każdym usunięciu, więc rzuca wyjątek środowiska wykonawczego, nawet jeśli próbowałem zrobić nowy obiekt.Usuń wybrane elementy z listy na liście

Próbowałem tak:

ListBox.SelectedObjectCollection selectedItems = new ListBox.SelectedObjectCollection(lstClientes); 
    selectedItems = lstClientes.SelectedItems; 
if (lstClientes.SelectedIndex != -1) 
{ 
    foreach (string s in selectedItems) 
     lstClientes.Items.Remove(s); 
} 
else 
    MessageBox.Show("Debe seleccionar un email"); 

Odpowiedz

28

Nie można modyfikować kolekcji podczas iteracji (stosując foreach) przez nią. Zamiast używać odwrotnego for pętlę:

ListBox.SelectedObjectCollection selectedItems = new ListBox.SelectedObjectCollection(lstClientes); 
selectedItems = lstClientes.SelectedItems; 

if (lstClientes.SelectedIndex != -1) 
{ 
    for (int i = selectedItems.Count - 1; i >= 0; i--) 
     lstClientes.Items.Remove(selectedItems[i]); 
} 
else 
    MessageBox.Show("Debe seleccionar un email"); 

Korzystanie odwrotnego pętli gwarantuje nie przeskoczyć każdy po wyjęciu.

+2

Tak, to jest to! Dziękuję Ci! tylko mała korekta: dla (int i = selectedItems.Count - 1; i> = 0; ** i - **) – Cristo

+0

Ups, good eye, thanks! –

+0

Może istnieć mały błąd, jeśli element istnieje dwa razy na liście elementów i wybierany jest tylko drugi. Myślę, że pierwszą można usunąć. Rozwiązanie z Items.RemoveAt (i) może być nieco lepsze. Ale ważniejsze będzie również odwrócenie iteracji! – Pieter21

6
selectedItems = lstClientes.SelectedItems; 

Linia ta nie tworzy nową kolekcję, ale ustawia odwołanie do tej w listbox. Więc przechodzisz przez kolekcję i próbujesz natychmiast usunąć z niej elementy. Nie jest możliwe

Można to wykorzystać, na przykład:

foreach (string s in lstClientes.SelectedItems.OfType<string>().ToList()) 
    lstClientes.Items.Remove(s); 
+0

Przepraszam, że nie skompilowałem dla mnie – Cristo

+1

@ CristobalDeIncógnitoFlipo youm probablym potrzebne do dodania 'using System. Linq; 'do twojej listy użycia, ponieważ ten kod używa LINQ do obiektów – horgh

+0

My bad. Nie znam linq. Ten działa zbyt ^^ – Cristo

6

Proste właśnie tak:

while (lst.SelectedItems.Count > 0) 
{ 
    lst.Items.Remove(lst.SelectedItems[0]); 
} 
+0

To jest brutalne, ale działa dobrze dla małych N. Odpowiedzi te wciąż pomijają coś bardzo eleganckiego - co mogło być sztuczką LINQ do wyodrębnienia indeksów i "odwrócenia" iteratora (trochę 'ToArray', a potem trochę magii ...). Cóż, obawiam się, że reverse pochodzi tylko z .NET 4.5: http://msdn.microsoft.com/pl-pl/library/bb358497%28v=vs.110%29.aspx –

1

znalazłem lepsze rozwiązanie.

 if (listBoxIn.SelectedItems.Count != 0) 
     { 
      while (listBoxIn.SelectedIndex!=-1) 
      { 
       listBoxIn.Items.RemoveAt(listBoxIn.SelectedIndex);     
      } 
     } 
+1

Witamy w Stack Overflow! Odpowiedzi dotyczące tylko kodu są tutaj prawie zawsze zbyt krótkie. Podaj kontekst swojej odpowiedzi. W tym przypadku, ponieważ pytanie jest bardzo stare, warto wskazać, dlaczego twoja odpowiedź dodaje coś dodatkowego do zaakceptowanej, przeczącej odpowiedzi. –

2
lst.Items.Remove(lst.Items[lst.SelectedIndex]); 

Można to wykorzystać, jeśli nie chcesz pętli

Uwaga: To działa tylko w celu usunięcia 1 pkt (wielokrotne pozycje usunie tylko pierwszy wybrany element)

0

jest to najbardziej najprostszy sposób, aby usunąć wybrane elementy

for(int v=0; v<listBox1.SelectedItems.Count; v++) { 
      listBox1.Items.Remove(listBox1.SelectedItems[v]); 
     } 
+0

Nie mogę uwierzyć, że ta odpowiedź jest poprawna. Czy lista SelectedItems nie zmienia się za każdym razem, gdy element zostanie usunięty z listy? W takim przypadku, gdy dojdziesz do pozycji V-1 do usunięcia, lista wybranych przedmiotów będzie zawierała tylko jeden przedmiot, a nie V. Powyższa odpowiedź, w której zawsze usuwasz pozycję zerową z listy SelectedItems, jest poprawna. –

+0

Co zrobić, jeśli ktoś wybrał wiele przedmiotów? –

1

I napotkał ten sam proble m dzisiaj i chcieliśmy czegoś nieco czystsze i wymyślił tego rozwiązania Linq:

foreach (int index in myListBox.SelectedIndices.Cast<int>().Select(x => x).Reverse()) 
    myListBox.Items.RemoveAt(index); 

zasadzie taki sam jak Patryka roztworu iteracji do tyłu i do usuwania wybranych elementów. Jednak zamiast powtarzać wstecz, odwracamy listę elementów do usunięcia i powtarzamy do przodu. Nie wykonujemy już iteracji nad oryginalnym wyliczeniem, więc możemy usuwać przedmioty z foreach.

0

Utwórz zmienną globalną:

public partial class Form1 : Form 
    { 

     Int32 index; 
    } 

Następnie w wybranej zmiany indeksu zapisać, że indeks w var zdefiniowanej:

private void lsbx_layers_SelectedIndexChanged(object sender, EventArgs e) 
     { 

      layerindex = lsbx_layers.SelectedIndices[0];//selected index that has fired the event 
     } 

Wreszcie usunąć element:

lsbx_layers.Items.RemoveAt(Layerindex); 
Powiązane problemy