2012-10-31 59 views
16

我想这样做,但是,列表框会在每次删除时发生变化,所以即使我试图做一个新对象,它也会抛出运行时异常。从列表框中删除选定的项目

我想是这样的:

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

回答

28

同时,通过它迭代(使用foreach)您不能修改的集合。相反,使用反向for循环:

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

使用反向循环确保你不取出之后,跳过所有。

+2

是的,就是这样!谢谢! 只是一个小小的更正: for(int i = selectedItems.Count - 1; i> = 0; ** i - **) – Cristo

+0

哎呀,好眼睛,谢谢! –

+0

如果一个项目在项目列表中存在两次,并且只有第二个项目被选中,那么可能会有一个小错误。我认为第一个可能会被删除。 Items.RemoveAt(i)的解决方案可能稍好一些。但是将迭代逆转也更重要! – Pieter21

6
selectedItems = lstClientes.SelectedItems; 

此行不会创建一个新的集合,而是设置为一个ListBox中的一个参考。因此,您正在遍历一个集合并尝试一次从其中删除项目。这是不可能的

您可以使用此功能,例如:

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

对不起,没有编译我 – Cristo

+1

@CristobalDeIncógnitoFlipo你可能需要添加'使用系统。 Linq;'到你使用的列表中,因为这段代码使用LINQ来对象 – horgh

+0

我的不好。我不知道linq。这个也可以工作^^ – Cristo

6

简单的就像这样:

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

这是残酷的,但对于小N工作正常。这些答案仍然错过任何优雅的东西 - 这可能是一些LINQ技巧来提取索引和“反转”迭代器(一些“ToArray”,然后一些魔术...... )。那么,我害怕反向只能使用.NET 4.5:http://msdn.microsoft.com/pl-pl/library/bb358497%28v=vs.110%29.aspx –

1

我找到了更好的解决方案。

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

欢迎使用堆栈溢出!代码只有答案在这里几乎总是过于简单。给你的答案一些背景。在这种情况下,由于问题非常古老,因此值得指出为什么您的答案会为已接受的最新答案增加额外的内容。 –

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

你可以使用这个,如果你不想循环

注意:这只能删除1项(多项选择它只会删除第一个选择项)

0

这是最简单的方法来删除选定的项目

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

我不能相信这个答案是正确的。每当从列表中删除某个项目时,SelectedItems列表是否会更改?在这种情况下,当您到达要移除的V-1项目时,所选项目列表将只有一个项目,而不是V项目。上面的答案,你总是从SelectedItems列表中删除第零个项目是正确的。 –

+0

如果某人选择了多个项目会怎么样? –

1

我遇到了同样的问题米今天想要的东西有点清洁,以及与此LINQ的解决方案提出了:

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

基本上一样向后迭代和删除所选项目的帕特里克的解决方案。然而,不是向后迭代,而是反转要删除和迭代转发的项目列表。我们不再遍历原始枚举,因此我们被允许删除foreach中的项目。

0

创建一个全局变量:

public partial class Form1 : Form 
    { 

     Int32 index; 
    } 

然后在选定的指数变化保存在您定义的VAR是指数:

private void lsbx_layers_SelectedIndexChanged(object sender, EventArgs e) 
     { 

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

最后,删除元素:

lsbx_layers.Items.RemoveAt(Layerindex);