简体   繁体   中英

Delete selected items from listbox

I want to do that but, the listbox changes on every deletion, so it throws runtime exception even if I tried to do a new object.

I tried like this:

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

You can't modify a collection while iterating (using a foreach ) through it. Instead use a reverse for loop:

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

Using a reverse loop ensures you don't skip over any after removing them.

selectedItems = lstClientes.SelectedItems;

This line does not create a new collection, but sets a reference to the one in a listbox. So you are iterating through a collection and try to remove items from it at once. It is not possible

You could use this, for example:

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

Simple just like this:

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

You can use this if you don't want to loop

Note: This only works to remove 1 item (multiple selections it will only remove the first selected item)

To build on Patrick's answer I tend to use a reverse index removal as it retains the index of items pending removal while they're being removed without removing identical items.

private void BtnDelete_Click(object sender, EventArgs e) {
    if (listBox.SelectedIndex == -1) {
        return;
    }

    // Remove each item in reverse order to maintain integrity
    var selectedIndices = new List<int>(listBox.SelectedIndices.Cast<int>());
    selectedIndices.Reverse();
    selectedIndices.ForEach(index => listBox.Items.RemoveAt(index));
}

I found better solution.

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

I encountered this same problem today and wanted something a bit cleaner, and came up with this Linq solution:

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

Basically the same as Patrick's solution of iterating backwards and removing selected items. However instead of iterating backwards, we reverse the list of items to remove and iterate forwards. We no longer iterate over the original enumeration, so we are allowed to remove items within the foreach.

This is the most easiest way to remove selected items

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

This works for multiple and single selections in WPF.

while (xListBox.SelectedItems.Count > 0)
{
    xListBox.Items.RemoveAt(SavedItemsListBox.SelectedIndex);
}

Create a global variable:

public partial class Form1 : Form
    {

        Int32 index;
    }

Then at the selected index change save that index in the var you defined :

 private void lsbx_layers_SelectedIndexChanged(object sender, EventArgs e)
        {

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

Finally ,remove the element :

 lsbx_layers.Items.RemoveAt(Layerindex);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM