2012-01-27 8 views
13

Tratando de cerrar todas las formas excepto para el menú principal usandoformas Cierre todos excepto el menú principal en C#

FormCollection formsList = Application.OpenForms; 

con un bucle foreach y diciendo,

if (thisForm.Name != "Menu") thisForm.Close(); 

que funciona bien, se omite el menú y cierra el primero, pero luego los errores:

Se modificó la colección; la operación de enumeración no puede ejecutar

y se detiene. He intentado algunos lugares, y todos dicen que este ciclo foreach es la manera de hacerlo, y es especialmente molesto ya que no estoy actualizando mi lista de formularios después de cerrar los formularios, lo que pensé que podría funcionar. Lo único que podía pensar era comenzar desde atrás y seguir adelante usando un rato.

Respuesta

53

Si utiliza foreach para enumerar a través de una colección, no se puede modificar (elementos agregados o eliminados) durante la iteración. Intente copiar las referencias a los formularios en otra colección, y luego elimínelos iterando a través de esa colección.

En situaciones como esta, que puede utilizar una lista o una simple matriz, tales como:

List<Form> openForms = new List<Form>(); 

foreach (Form f in Application.OpenForms) 
    openForms.Add(f); 

foreach (Form f in openForms) 
{ 
    if (f.Name != "Menu") 
     f.Close(); 
} 

O puede utilizar un bucle for:

for (int i = Application.OpenForms.Count - 1; i >= 0; i--) 
{ 
    if (Application.OpenForms[i].Name != "Menu") 
     Application.OpenForms[i].Close(); 
} 

O, mi nuevo y actual favorito, puede utilizar el método atrás():

foreach (Form f in Application.OpenForms.Reverse()) 
{ 
    if (f.Name != "Menu") 
     f.Close(); 
} 
+5

Nota para los demás - Invertir no parece estar disponible en .NET marco 4. –

2

Eso ocurre cuando la colección se cambia dentro de un bucle foreach que lo usa. Está eliminando un elemento del formsList dentro del bucle.

Prueba esto:

for (int i = formsList.Count-1; i > 0; i--) 
{ 
    if (formsList[i].Name != "Menu") 
    { 
     formsList[i].Close(); 
    } 
} 
0

Como los estados de error, no se puede modificar una colección en su foreach.

En su lugar, puede usar un lazo hacia atrás for.

0

como la colección de formularios se actualiza para cada iteración. Cuando cierra un formulario, se elimina de la colección de formularios. es como quitar un objeto de la memoria mientras está usando.

2

He aquí un método aún más concisa que utiliza el mismo número de li define como el método original:

Form[] forms = Application.OpenForms.Cast<Form>().ToArray(); 
foreach (Form thisForm in forms) 
{ 
    if (thisForm.Name != "Menu") thisForm.Close(); 
} 

Al usar el método de extensión de LINQ Cast, se puede evitar un bucle a través de la colección de construir una matriz.

0

Se modificó la colección; la operación de enumeración no se puede ejecutar.

FormCollection formsList = Application.OpenForms; 
      //for (int i = 0; i < formsList.Count; i++) 
      foreach(Form f in formsList) 
      { 
       if (f.Name != "Form1" || f.Name != "Home" || f.Name != "AdminHome") 
        f.Close(); 
      } 
      this.Close(); 
2

para cerrar todas las formas:

 for (int i = Application.OpenForms.Count - 1; i >= 0; i--) 
     { 
      if (Application.OpenForms[i].Name != "Menu") 
       Application.OpenForms[i].Close(); 
     } 
0

Sé que esto es viejo, pero yo necesitaba para llevar a cabo este mismo escenario y se le ocurrió una manera elegante y sencilla de lograr esto de la siguiente

 Form[] formsList = Application.OpenForms.Cast<Form>().Where(x => x.Name == "Form1").ToArray(); 
     foreach (Form openForm in formsList) 
     {     
      openForm.Close(); 
     } 

Esto cerrará TODAS las ventanas que se abrieron llamadas Form1

Cuestiones relacionadas