2012-01-27 9 views
13

Cercando di chiudere tutte le forme tranne che per il menu principale conforme Chiudere tutte ad eccezione del menu principale in C#

FormCollection formsList = Application.OpenForms; 

con un ciclo foreach e dicendo,

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

che funziona bene, è salta il menu, e chiude il primo, ma poi gli errori:

Raccolta è stata modificata; operazione di enumerazione non può essere eseguita

e fermate. Ho provato alcuni punti e tutti dicono che questo ciclo foreach è il modo per farlo, ed è particolarmente fastidioso visto che non sto aggiornando la mia lista dei moduli dopo aver chiuso i moduli, che pensavo potesse funzionare. L'unica cosa che potevo pensare era di iniziare da dietro e lavorare avanti usando un po '.

risposta

53

Se si utilizza foreach per eseguire l'enumerazione tramite una raccolta, non può essere modificato (elementi aggiunti o rimossi) durante l'iterazione. Prova a copiare i riferimenti ai moduli in un'altra raccolta, quindi rimuovili iterando attraverso quella raccolta.

in situazioni come questa, è possibile utilizzare un elenco o una matrice semplice, come ad esempio:

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

Oppure si può utilizzare un ciclo for:

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

Oppure, la mia nuova e corrente preferito, è possibile utilizzare il metodo reverse():

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

Nota per gli altri - Reverse non sembra disponibile in .NET quadro 4. –

2

Ciò accade quando la raccolta viene modificata all'interno di un ciclo foreach che la utilizza. Stai rimuovendo un articolo da formsList all'interno del ciclo.

Prova questo:

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

Come afferma di errore, non è possibile modificare una collezione nella sua foreach.

Invece, è possibile utilizzare un ciclo all'indietro for.

0

mentre la raccolta moduli viene aggiornata per ogni iterazione. Quando chiudi un modulo, viene rimosso dalla raccolta moduli. è come rimuovere un oggetto dalla memoria mentre lo sta usando.

2

Ecco un metodo ancora più conciso che utilizza lo stesso numero di Li nes come vostro metodo originale:

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

utilizzando il metodo di estensione di Linq Cast, si può evitare il ciclo attraverso la raccolta di costruire un array.

0

La raccolta è stata modificata; l'operazione di enumerazione potrebbe non essere eseguita.

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

per chiudere tutte le forme:

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

So che questo è vecchio, ma avevo bisogno di eseguire questo stesso scenario e si avvicinò con un modo elegante e semplice per raggiungere questo obiettivo come segue

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

Chiuderà TUTTE le finestre che erano aperte chiamato Form1

Problemi correlati