collections被修改; 枚举可能不会执行错误从LIstBox中删除一个ListItem

我有两个ListBox,lstAvailableColors和lstSelectedColors。 每个列表框之间有两个button,即添加和删除。 当在lstAvailableColors中select一个或多个颜色并单击Addbutton时,我想从lstAvailableColors中移除它们并将它们显示在lstSelectedColors中。 此外,如果在lstSelectedColors中select了颜色,并单击删除button,我想从lstSelectedColors中删除颜色并将其添加回到lstAvailableColors。 当我这样做,当它删除项目时,我得到以下错误:

collections被修改; 枚举操作可能无法执行。

这里是添加button和删除button的代码:

加:

protected void btnAdd_Click(object sender, EventArgs e) { foreach (ListItem item in lstAvailableColors.Items) { if (item.Selected) { lstSelectedColors.Items.Add(item); lstAvailableColors.Items.Remove(item); } } } 

去掉:

 protected void btnRemove_Click(object sender, EventArgs e) { foreach (ListItem item in lstSelectedColors.Items) { if (item.Selected) { lstAvailableColors.Items.Add(item); lstSelectedColors.Items.Remove(item); } } } 

在.Net中枚举集合时,无法修改集合。 你需要分开你的枚举和删除代码到不同的块。 这里有一个关于如何在没有LINQ的情况下做一个快速的例子

 protected void btnAdd_Click(object sender, EventArgs e) { var selected = new List<ListItem>(); foreach (ListItem item in lstAvailableColors.Items) { if (item.Selected) { selected.Add(item); lstSelectedColors.Items.Add(item); } } foreach (ListItem item in selected) { lstAvailableColors.Items.Remove(item); } } 

这里是一个更简洁的使用LINQ的版本

 var selected = lstAvailableColors.Cast<ListItem>().Where(i => i.Selected).ToList(); selected.ForEach( x => { lstSelectedColors.Items.Add(x); }); selected.ForEach( x => { lstAvailableColors.Items.Remove(x);}); 

编辑

LINQ版本分为两部分。 第一部分是查找当前选定项目并将值存储在List<ListItem>的第一行。 该行包含.ToList()调用是非常重要的,因为这会强制查询立即执行,而被延迟执行。

接下来的两行遍历每个选定的值并删除或将其添加到适当的列表中。 由于选定的列表已经存储,所以在修改时我们不再列举集合。

当您使用枚举器作为这个集合时,您无法修改集合,每个语句的作用是什么。

您必须使用正常for循环来循环数据,然后才能修改集合,但是如果插入或删除元素,则必须小心地正确更新当前索引。 如果你只是添加或删除元素,而不插入一些,从最后一个元素迭代到第一个将做。

 protected void btnAdd_Click(object sender, EventArgs e) { for (Int32 i = lstAvailableColors.Items.Count; i >= 0; i--) { ListItem item = lstAvailableColors.Items[i]; if (item.Selected) { lstSelectedColors.Items.Add(item); lstAvailableColors.Items.Remove(item); } } } 

你不能修改你正在迭代的集合。 一般来说,这种types的问题的一个好的解决scheme是创build一个空的集合,并在你的迭代器中复制你不想删除的所有元素; 迭代完成后,将原始集合replace为新集合。

正如上面提到的其他答案,在完成迭代之前,您无法删除项目。 所以也许这样的事情对你来说是最干净的:

 var itemsToRemove = lstAvailableColors.Items.Cast<ListItem>().Where(i => i.IsSelected).ToArray(); foreach(ListItem item in itemsToRemove) lstAvailableColors.Remove(item); 

迭代时不能修改集合。 要么迭代一个副本,要么使用,反向迭代,并删除。

有关如何删除所选项目的示例。 这里只有选定的索引被取走。

  public void RemoveSelectedItems(ListBox listbox) { List<ListItem> items = GetSelectedItems(listbox); foreach (var listItem in items) { listbox.Items.Remove(listItem); } } public List<ListItem> GetSelectedItems(ListBox listbox) { int[] selectedIndices = listbox.GetSelectedIndices(); return selectedIndices.Select(index => listbox.Items[index]).ToList(); } 

也许这是你需要的

 protected void btnAdd_Click(object sender, EventArgs e) { while(listBox1.SelectedIndex!=-1) { listBox1.Items.Remove(listBox1.SelectedItem); } } 

这可能会帮助你;

去除:

 protected void btnRemove_Click(object sender, EventArgs e) { { for (int i = 0; i < lstAvailableColors.Items.Count; i++) { if(lstAvailableColors.Items[i].Selected) lstAvailableColors.Items.RemoveAt(i); } } } 

你面对的问题是,你不能修改你通过的集合。 你可以通过使用一个linq解决这个问题:

 protected void btnAdd_Click(object sender, EventArgs e) { lstAvailableColors.Items.RemoveAll(ac => ac.Selected); }