C#在多格式应用程序中关闭特定窗体

C#在多格式应用程序中关闭特定窗体,c#,winforms,C#,Winforms,我希望你能帮我做这个。我的应用程序正在监视数据库中的警报。当数据库中显示警报时,我的应用程序会将其添加到datagridview的主窗体中,并根据其优先级创建一个带有该事件的小型winform弹出窗口 datagridview中有一个按钮,用于将警报标记为“已看到”,然后它将更新数据库,并从列表中删除。但是,此事件的弹出窗体仍处于打开状态 有人知道如何关闭此表单吗?我需要一种方法在可能打开的多个警报表单之间找到特定表单 到目前为止,我最接近的代码是以下代码: private void close

我希望你能帮我做这个。我的应用程序正在监视数据库中的警报。当数据库中显示警报时,我的应用程序会将其添加到datagridview的主窗体中,并根据其优先级创建一个带有该事件的小型winform弹出窗口

datagridview中有一个按钮,用于将警报标记为“已看到”,然后它将更新数据库,并从列表中删除。但是,此事件的弹出窗体仍处于打开状态

有人知道如何关闭此表单吗?我需要一种方法在可能打开的多个警报表单之间找到特定表单

到目前为止,我最接近的代码是以下代码:

private void closeForm(int id)
{
    foreach (Form f in Application.OpenForms)
    {
        if (Convert.ToString(id) == f.Name)
        {
            this.Close();
        }
    }
}
直到它关闭正确的窗体为止。然后它给出了一个错误,说“集合已修改;枚举操作可能无法执行。”这有点道理,但我无法找到其他方法来执行它

我有一个名为
Alert
的winform类,用于生成新表单。如您所见,他们将获得一个标准文本“报警”和一个基于报警ID的唯一名称

Alert alertform = new Alert(id);
alertform.Name = formid;
alertform.Text = "Alarm";
alertform.Show();

我希望有人能给我一些好主意,我该怎么做。我已经搜索过了,但找不到一个简单而优雅的方法来实现这一点。

您应该能够在
DataGridView
或其
数据源中存储对表单的引用,然后使用该引用关闭表单。与迭代所有应用程序表单相比,这种方法在将来不太可能中断

最好的方法可能是在保存表单id的
DataGridView
中添加一个隐藏列,然后还有一个
字典,用于获取对要关闭表单的引用

然后,您只需从字典中获取表单引用并调用close即可:

private void CloseAlertForm(int id)
{        
    Form f = dict[id];
    f.Close();
    dict.Remove(id);
}

此外,您可以存储
操作
委托,而不是表单引用,从而允许您稍微解耦警报表单和网格表单。

您需要添加中断;在关闭表单后返回到循环。关闭表单时会修改集合(该表单将从集合中删除),从而使foreach循环无效。你不应该叫f.Close而不是这个,Close

private void closeForm(int id)

    {
        foreach (Form f in Application.OpenForms)

            if (Convert.ToString(id) == f.Name)
            {
                f.Close();
                break;

            }
    }

只需从
foreach
循环中获取ref.并在其外部关闭
表单即可

private void closeForm(int id)
{   
        Form formtoclose=null;
        foreach (Form f in Application.OpenForms)
        {
            if (Convert.ToString(id) == f.Name)
            {
                formtoclose = f;
            }
        }
        if(formtoclose!=null)
        formtoclose.Close();
}

关闭会修改OpenForms集合,因此您可以在副本上枚举,而不是直接枚举OpenForms集合

LINQ制作副本非常方便,如下所示:

foreach (Form f in Application.OpenForms.Where(i => Convert.ToString(id) == i.Name).ToList()) {
      // Save to close the form here
}

ToList执行查询并存储副本。

您可以使用表单的类型来查找它们(和
ToArray
创建新集合,以避免更改正在枚举的集合)


您能为此键入一点示例代码吗?不是为了存储对datagridview的引用,而是如何使用它来关闭表单。所有的男生(可能还有女生)我都很惊讶我得到了这么多很棒的答案和这么快的速度。我找到了一个对我有效的解决方案,并不是说其他的也不是很好的解决方案。但是我只需要一个:-)这个对我来说是最容易实现的。谢谢大家的回复!林克的米克尔;)
var f=Application.OpenForms.Cast().Where(form=>form.Name==id.FirstOrDefault();如果(f!=null)f.Close()您的代码将不会编译,因为
formtoclose
未分配。在循环之前,您必须将
formtoclose
设置为null(显然,在调用
Close
之前,您必须检查它是否仍然为null)。是的,我检查了这一点,但它没有编译。+1,这是解决问题背后的两个问题的最直接的方法:关闭此表单而不是找到的表单,并在ForEach@Konrad Application.Forms中执行它,它是一个“原始”列表;它不支持像“Cast”这样的Linq操作符。这段代码永远不会编译。这看起来是解决我问题的一个非常好和简单的解决方案。但是由于某种原因,它关闭了我的整个应用程序。@Mike您是否将“this.Close();”更改为“f.Close();”?@Mike在编辑中添加了该注释,因为我只是在发布代码示例后才注意到它,对不起。但很高兴您找到了解决方案。这只适用于同时显示一个警报的情况,但也适用于:D@VirtualBlackFox据我所知,他只想关闭被点击为“已看到”的警报,而不是所有警报。所有的男生(可能还有女生)我都很惊讶我得到了这么多很棒的答案,而且速度如此之快。我找到了一个对我有效的解决方案,并不是说其他的也不是很好的解决方案。但是我只需要一个:-)这个对我来说是最容易实现的。谢谢大家的回复!表单是一个“原始”列表;它不支持像“Where”这样的Linq操作符。这段代码永远不会编译。Application.Forms是一个“原始”列表;它不支持像“Select”这样的Linq操作符。这段代码永远不会编译。Application.Forms是一个“原始”列表;它不支持像“Where”这样的Linq操作符。这段代码永远不会编译。
private void CloseAlerts()
{
    var openForms = Application.OpenForms.Cast<Form>();
    foreach (var f in openForms.Where(f => f is Alert).ToArray())
    {
        f.Close();
    }
}
Alert alertform = new Alert(id);

alertform.Text = "Alarm";

alertform.Show();
var names = Application.OpenForms.Select(rs=>rs.name).ToList()

foreach (string name in names)
    if (Convert.ToString(id) == name)
    {
        Application.OpenForms[name].Close();
    }