8

我有两个 ListBox,lstAvailableColors 和 lstSelectedColors。每个列表框之间有两个按钮,添加和删除。当在 lstAvailableColors 中选择一种或多种颜色并单击“添加”按钮时,我想将它们从 lstAvailableColors 中删除并在 lstSelectedColors 中显示它们。此外,如果在 lstSelectedColors 中选择了颜色并单击了“删除”按钮,我想从 lstSelectedColors 中删除颜色并将它们添加回 lstAvailableColors。当我这样做时,我在删除项目时收到以下错误:

收藏已修改;枚举操作可能无法执行。

这是添加按钮和删除按钮的代码:

添加:

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

10 回答 10

18

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

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

于 2009-04-30T17:08:03.567 回答
6

当您为该集合使用 Enumerator 时,您不能修改集合,for each 语句的作用。

您必须使用普通的 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);
        }
    }
}
于 2009-04-30T17:06:27.643 回答
5

您不能修改正在迭代的集合。一般来说,这类问题的一个好的解决方案是创建一个空集合,然后在迭代器中复制所有不想删除的元素;迭代完成后,将原始集合替换为新集合。

于 2009-04-30T17:08:28.247 回答
3

正如提到的另一个答案,在完成迭代之前您不能删除项目。所以也许这样的东西对你来说是最干净的:

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

foreach(ListItem item in itemsToRemove) lstAvailableColors.Remove(item);
于 2009-04-30T17:08:24.330 回答
1

迭代集合时不能修改集合。遍历副本或使用 for,反向迭代并在您向下移动时删除。

于 2009-04-30T17:04:26.587 回答
0

有关如何删除所选项目的示例。此处仅获取和删除选定的索引。

   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();
  }
于 2010-10-16T13:56:12.983 回答
0

也许这就是你需要的

protected void btnAdd_Click(object sender, EventArgs e)
{
    while(listBox1.SelectedIndex!=-1)
    {
           listBox1.Items.Remove(listBox1.SelectedItem);
    }
}
于 2012-07-05T05:58:28.777 回答
0

这可能会对您有所帮助;

去除:

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);
        }
    }
}
于 2013-02-01T04:11:47.277 回答
0

您面临的问题是您无法修改您遍历的集合。您可以通过使用单个 linq 来解决此问题:

protected void btnAdd_Click(object sender, EventArgs e)
{
    lstAvailableColors.Items.RemoveAll(ac => ac.Selected);
}
于 2015-09-23T17:51:09.373 回答
0

您可以使用这个通用函数从 ObservableCollection 中删除多个项目(我知道很多人害怕异常,但异常只不过是一个开发工具)

    public static void OCRemoveMultiple<T>(ref ObservableCollection<T> inputList, IList<T> toRemoveItems)
    {
        REITERATE:
        {
            try
            {
                while( inputList.Intersect<T>(toRemoveItems).Any())
                {
                    var intersectionList = inputList.Intersect<T>(toRemoveItems);
                    foreach (var item in intersectionList)
                    {
                        inputList.Remove(item);
                    }
                }

            }
            catch (Exception)
            {
                goto REITERATE;
            }
        }
    }

这是一个测试用例(示例)如何使用它:

        ObservableCollection<object> targetList = new ObservableCollection<object>();

        targetList.Add("T1");
        targetList.Add("T2");
        targetList.Add("B3");
        targetList.Add("B4");
        targetList.Add("T5");

        IList<object> toRemove = targetList.ToList().Where(k=>k.ToString().Contains("B")).ToList();

        OCRemoveMultiple(ref targetList, toRemove);

        targetList.ToList().ForEach(k => Console.WriteLine(k.ToString())); // Writes "T1", "T2" and "T5"
于 2021-02-18T13:00:56.677 回答