La colección fue modificada; la enumeración no puede ejecutar el error al eliminar un ListItem de un LIstBox

Tengo dos ListBoxes, lstAvailableColors y lstSelectedColors. Entre cada cuadro de lista hay dos botones, Agregar y Eliminar. Cuando se selecciona un color o colores en lstAvailableColors y se hace clic en el botón Agregar, quiero eliminarlos de lstAvailableColors y mostrarlos en lstSelectedColors. Además, si se seleccionan colores en lstSelectedColors y se hace clic en el botón Eliminar, quiero eliminar los colores de lstSelectedColors y agregarlos a lstAvailableColors. Cuando hago esto, aparece el siguiente error cuando elimina el elemento:

La colección fue modificada; la operación de enumeración no se puede ejecutar.

Aquí está el código para el botón Agregar y el botón Eliminar:

Añadir:

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

Retirar:

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

No es posible modificar una colección mientras la está enumerando en .Net. Debe separar su enumeración y eliminar el código en diferentes bloques. Aquí hay una muestra rápida sobre cómo hacer eso sin LINQ

 protected void btnAdd_Click(object sender, EventArgs e) { var selected = new List(); 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); } } 

Y aquí hay una versión más concisa usando LINQ

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

EDITAR

La versión LINQ funciona en dos partes. La primera parte es la primera línea que encuentra los elementos seleccionados actualmente y almacena el valor en una List . Es muy importante que la línea contenga la llamada .ToList () porque obliga a que la consulta se ejecute inmediatamente frente a la ejecución diferida.

Las siguientes dos líneas iteran a través de cada valor que se selecciona y lo elimina o lo agrega a la lista apropiada. Debido a que la lista seleccionada ya está almacenada, ya no enumeramos la colección cuando la modificamos.

No puede modificar una colección mientras está usando un Enumerador para esta colección, lo que hace para cada instrucción.

Debe recorrer los datos con un ciclo for normal y luego puede modificar la colección, pero debe tener cuidado de actualizar correctamente el índice actual si inserta o elimina elementos. Si solo agrega o elimina elementos y no inserta algunos, será suficiente iterar desde el último elemento hasta el primero.

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

No puede modificar una colección sobre la que está iterando. En general, una buena solución para este tipo de problema es crear una colección vacía, y en su iterador, copiar sobre todos los elementos que NO desea eliminar; una vez completada la iteración, reemplace la colección original con su nueva colección.

Como la otra respuesta mencionada, no puede eliminar elementos hasta que haya completado la iteración. Entonces quizás algo como esto será más limpio para ti:

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

No puede modificar una colección mientras está iterando sobre ella. Repita una copia o use para, itere en reversa y elimine a medida que baja.

Ejemplo sobre cómo eliminar los elementos seleccionados. Aquí solo los índices seleccionados son tomados y eliminados.

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

Quizás esto es lo que necesitas

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

Esto podría ayudarte;

Para eliminar:

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

El problema que enfrenta es que no puede modificar la colección a través de la cual se procesa. Puedes resolver esto usando un solo linq:

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