2

I'm using WinForms. I want to close all of the forms except my main form called Form1. I noticed that my main Form is index 0, so i was wondering if i could do something like, close all the forms except of index 0. How can i do this? This is what i have so far.

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

  foreach (Form f in Application.OpenForms)
  {
        openForms.Add(f);
        int mainFormIndex = openForms.IndexOf(0);
        Console.WriteLine(": " + mainFormIndex);


        if(mainFormIndex != 0)
        {
           this.Owner.Close();
           }
           else
           {
             this.Close();
           }
        }
  }
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
taji01
  • 2,527
  • 8
  • 36
  • 80

2 Answers2

3

You can close all forms except Form1 instance using linq this way:

Application.OpenForms.Cast<Form>().Where(x => !(x is Form1))
           .ToList().ForEach(x => x.Close());
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • There's one caveat (though it's an unlikely scenario): If you have more than one instance of `Form1` (where one of these is the main window), this might close the wrong one. – stakx - no longer contributing Nov 12 '16 at 10:29
  • @stakx Thanks for the feedback. Good point, the OP should pay attention to caveats. When the OP learned how to use `Application.OpenForms` and linq, they will find a solution for such cases, for example the can find the main form and using `Except`, exclude it from the forms and close other forms. For example something like what I used for [Close All But This](http://stackoverflow.com/a/34845445/3110834) – Reza Aghaei Nov 12 '16 at 10:36
  • In most cases there is only one open instance of the Main form, but if for any reason you may have more than one instance, you can keep a reference of it in a static property in `Program.cs` and use it as reference of Main form and write a code like `Application.OpenForms.Cast
    ().Except(Program.MainForm).ToList().ForEach(x => x.Close());`.
    – Reza Aghaei Nov 12 '16 at 10:40
  • Yes, it needs some corrections :) `Application.OpenForms.Cast
    ().Except(new Form[] { Program.MainForm }).ToList().ForEach(x => x.Close());`
    – Reza Aghaei Nov 12 '16 at 17:37
1

You can check the name of Form and then close, for example if you need to keep Form1 open and close all other forms;

for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
    if (Application.OpenForms[i].Name != "Form1")
    {
        Application.OpenForms[i].Close();
    }
}
Damith
  • 62,401
  • 13
  • 102
  • 153
  • Wow thank you I've been trying this for a while now :) – taji01 Nov 12 '16 at 09:15
  • While this might work, I believe it to be bad practice. It makes some assumptions about a form instance's `Name` property value, which is in all likelihood set only in designer-generated code. If you rename the `Form1` class, this might or might not (subject to the Forms designer's whim) affect the form instance's `Name` property value; you'll have to remember to manually keep the `"Form1"` string literal "in sync". That's why I believe [this answer](http://stackoverflow.com/a/40561790/240733) has less potential of causing regression bugs. – stakx - no longer contributing Nov 12 '16 at 10:26
  • @Damith I believe using type is much better, but using `Name` is not such bad idea to deserve a downvote. (+1) Also using linq makes the code really more readable than a reverse for loop :) – Reza Aghaei Nov 12 '16 at 20:44