关闭所有打开的窗体,C#中的主菜单除外

本文关键字:菜单 窗体 | 更新日期: 2023-09-27 18:21:38

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

FormCollection formsList = Application.OpenForms;

用foreach循环说,

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

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

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

并停止。我试过几个地方,他们都说foreach循环是实现这一点的方法,这尤其令人讨厌,因为我在关闭表单后没有更新表单列表,我认为这可能会奏效。我唯一能想到的就是从后场开始,利用一段时间向前推进。

关闭所有打开的窗体,C#中的主菜单除外

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

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

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

或者你可以使用for循环:

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

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

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

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

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

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

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

试试这个:

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

关闭所有表单:

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

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

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

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

由于错误状态,您无法在其foreach中修改集合。

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

因为表单集合在每次迭代中都在更新。关闭表单时,它将从表单集合中删除。这就像在使用时从内存中删除一个对象。