在 C# 中关闭除主菜单之外的所有打开的表单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9029351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 05:40:13  来源:igfitidea点击:

Close all open forms except the main menu in C#

c#winforms

提问by Ryan Durrant

Trying to close all forms except for the main menu using

尝试关闭除主菜单之外的所有表单使用

FormCollection formsList = Application.OpenForms;

with a foreach loop and saying,

用 foreach 循环说,

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

Which works ok, it skips the menu, and closes the first, but it then errors:

哪个工作正常,它跳过菜单,并关闭第一个,但随后出现错误:

Collection was modified; enumeration operation may not execute

集合被修改;枚举操作可能不会执行

and stops. I have tried a few places, and they all say that this foreach loop is the way to do it, and it is especially annoying as I am not updating my forms list after closing the forms, which I thought might work. The only thing I could think of was to start at the back and work forward using a while.

并停止。我已经尝试了几个地方,他们都说这个 foreach 循环是这样做的,它特别烦人,因为我在关闭表单后没有更新我的表单列表,我认为这可能有效。我唯一能想到的就是从后面开始,然后用一段时间向前推进。

采纳答案by Trevor Elliott

If you use foreach to enumerate through a collection, it can't be modified (items added or removed) during the iteration. Try copying references to the forms to another collection, and then remove them by iterating through that collection.

如果您使用 foreach 来枚举一个集合,则在迭代期间不能对其进行修改(添加或删除项目)。尝试将表单引用复制到另一个集合,然后通过迭代该集合来删除它们。

In situations like this, you can use a list or a simple array, such as:

在这种情况下,您可以使用列表或简单数组,例如:

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

Or you can use a for loop:

或者您可以使用 for 循环:

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

Or, my new and current favorite, you can use the Reverse() method:

或者,我新的和当前最喜欢的,您可以使用 Reverse() 方法:

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

回答by annonymously

That happens when the collection is changed inside a foreach loop that uses it. You are removing an item from formsListinside the loop.

当在使用它的 foreach 循环内更改集合时,就会发生这种情况。您正在从formsList循环内部删除一个项目。

Try this:

尝试这个:

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

回答by SLaks

As the error states, you can't modify a collection in its foreach.

正如错误所述,您无法在其 foreach 中修改集合。

Instead, you can use a backwards forloop.

相反,您可以使用向后for循环。

回答by Ravi Gadag

as the form collection is updating for every iteration. When you close a form, it is removed from the form collection. it's like removing a object from memory while it is using .

因为每次迭代都会更新表单集合。当您关闭表单时,它会从表单集合中删除。这就像在使用 .

回答by Abraham

Here's an even more concise method that uses the same number of lines as your original method:

这是一个更简洁的方法,它使用与原始方法相同的行数:

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

By using Linq's extension method Cast, you can avoid looping through the collection to build an array.

通过使用 Linq 的扩展方法Cast,可以避免循环遍历集合来构建数组。

回答by sulaiman

Collection was modified; enumeration operation may not execute.

集合被修改;枚举操作可能无法执行。

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

回答by maneesh

To Close all forms :

关闭所有表格:

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

回答by Darren Lawrence

I know this is old but I needed to perform this same scenario and came up with a elegant and simple way to achieve this as follows

我知道这很旧,但我需要执行相同的场景,并想出了一种优雅而简单的方法来实现这一点,如下所示

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

This will close ALL windows that where opened called Form1

这将关闭所有打开的名为 Form1 的窗口