8

lstAvailableColorsとlstSelectedColorsの2つのリストボックスがあります。各リストボックスの間には、[追加]と[削除]の2つのボタンがあります。lstAvailableColorsで1つまたは複数の色を選択し、[追加]ボタンをクリックした場合、それらを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 バージョンは 2 つの部分で動作します。最初の部分は、現在選択されている項目を検索し、値を に格納する最初の行List<ListItem>です。行に .ToList() 呼び出しが含まれていることは非常に重要です。これにより、クエリがすぐに実行されるのではなく、実行が遅れることが強制されるためです。

次の 2 行は、選択された各値を繰り返し処理し、適切なリストに削除または追加します。選択したリストは既に保存されているため、コレクションを変更するときにコレクションを列挙する必要はありません。

于 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

多分これはあなたが必要とするものです

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

選択したアイテムを削除する方法の例。ここでは、選択されたインデックスのみが取得され、削除されます。

   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 に答える