C# 确定MDI表单是否打开

C# 确定MDI表单是否打开,c#,winforms,C#,Winforms,我有一个基本表单(BaseMDIForm),几个表单(客户机、库存、订单等)从中继承。在此基本窗体上有一个受保护的字符串“windowID”。此id由每个表单设置,作为唯一标识当前在该表单中打开的对象(Client.id、Inventory.id、Order.id等)的方法 我在客户端窗体上成功地使用此方法在任何打开的客户端窗体上查找特定的客户端id: // method is in the Client form (and is coded to specifically look for C

我有一个基本表单(BaseMDIForm),几个表单(客户机、库存、订单等)从中继承。在此基本窗体上有一个受保护的字符串“windowID”。此id由每个表单设置,作为唯一标识当前在该表单中打开的对象(Client.id、Inventory.id、Order.id等)的方法

我在客户端窗体上成功地使用此方法在任何打开的客户端窗体上查找特定的客户端id:

// method is in the Client form (and is coded to specifically look for Client forms)
private Boolean FindFormWithWindowID(string windowID)
{
    foreach (Form form in this.MdiParent.MdiChildren)
    {
        if (form.GetType() == typeof(frmClient))
        {
            frmClient clientForm = (frmClient)form;
            if (clientForm.windowID == windowID)
            {
                // close this form because the client is open on an existing form
                if (this.windowID == "") // this won't be set yet if we're searching for an existing form
                    Close();

                form.Activate();
                return true;
            }
        }
    }
}
这个概念背后的想法是,当用户试图打开一个已经在现有表单上打开的客户机记录(或库存、订单等)时,现有表单会得到关注并被带到最前面(然后关闭新打开的表单)

我正在尝试将此方法移动到基本表单,这样就不需要在任何继承表单中不断创建此方法,只需从这些表单中调用,如:

if (!FindFormWithWindowID(ClientForm, windowID))
{
    // continue loading new form
}

是否有方法传入表单类型(客户机、库存、订单等),然后让此新的基本方法通过传入的特定表单类型的现有MdiChildern循环,以查找包含给定窗口id的特定表单(请记住,此方法将从许多不同类型的继承表单中调用)?我试图避免添加switch语句来确定表单类型,因为这将迫使我在项目中添加全新表单时更新它

窗体上实际上不存在WindowID,因此我假设您的窗体继承了一个基本窗体,并将WindowID添加到该窗体中

public InheritedForm : Form
{
    public string WindowID { get; set; }
}
如果是这种情况,则可以将当前的FindFormWithWindowID方法替换为:

string windowidtolookfor = "1234";

InheritedForm foundform = Application.OpenForms.OfType<InheritedForm>().Where(f => f.WindowID = windowidtolookfor).FirstOrDefault();

对于固定数量的类型,可以传递表示该类型的字符串,然后检查每个windows类型是否匹配

System.Type getTypeOfForm(string docType) {
    switch (docType) {
        case "Customer":
            return typeof(MyNameSpace.CustomerMDIForm);
        case "Invoice":
            return typeof(MyNameSpace.InvoiceMDIForm);
        case "Order":
            return typeof(MyNameSpace.OrderMDIForm);

            ...

        default:
            throw new Exception("Unknown Form Type");
    }
}
通过将返回的运行时类型插入到“==typeof(frmClient)”,可以将返回类型缝合到现有循环中。如果传递了目标表单类型的完全限定类字符串,还可以使用System.GetType(string)将其转换为System.type对象

如果您只需将System.type变量传递给搜索,还可以避免任何字符串到类型映射的恶作剧:

if (!FindFormWithWindowID(typeof(MyNameSpace.CustomerMDIForm), windowID))

为什么移动这种方法是一个问题还不是很明显。您可能应该向frmClient添加另一个方法,例如,在尝试创建frmChild之前,静态void CreateClient(stringid)执行此检查。并且,假设只有一个MdiParent实例,向该表单添加一个静态方法,该方法返回唯一的实例。代码流如下(对于客户端,但对于所有类型的表单基本相同):打开客户端表单,显示客户端列表供用户选择。稍后,在打开多个客户端窗口后,用户决定打开以前选择的客户端窗体(忘记它仍然打开)。因此,新表单打开,列表显示,用户选择客户端。现在我们检查客户机表单是否已经打开。因此,在打开新的客户端窗体以允许用户从中选择客户端之前,我们无法检查打开的客户端。windowID位于基本窗体上,因此每个继承的窗体都会获取该变量。我可能没有正确阅读您的示例,但它们不都要求将特定类型的表单编码到调用中(即“InheritedForm”和“MyForm”)?我希望能够传入要查找的表单类型,然后针对给定的windowID只搜索那些特定类型的表单。来自客户端窗口的一个示例调用是如果(!FindFormWithWindowID(ClientForm,windowID)){//继续加载新表单}我不知道您的基本表单类型是什么,所以我添加了一个名为InheritedForm的函数,这样代码就有意义了。正如我所说的,您可以在任何地方调用此函数,只需将or替换为您的表单类型。所以,若你们的表单是带有lotsofButtonson的form类型,那个么你们就把它改为of类型。这个解决方案的好处在于,您摆脱了完整的方法,依靠Linq查询来完成同样的事情。在您通常调用FindFormWithWindowID的地方,您只需将其替换为linq查询即可。再次查看,您的解决方案将满足我的需要。这些调用需要添加到每个继承的表单中,而不是添加到基表单中。谢谢大家的帮助,没错,您只需将这一行放在需要执行检查的任何位置,而不必让您的find方法对每个表单都可用。我目前有一个版本可以使用此方法,但我希望避免必须打开传入的表单类型,因为这将导致代码需要为添加到表单中的每个新表单类型进行更新解决方案假设对该方法进行了调用,“default”将有助于捕获未添加新表单的时间。
System.Type getTypeOfForm(string docType) {
    switch (docType) {
        case "Customer":
            return typeof(MyNameSpace.CustomerMDIForm);
        case "Invoice":
            return typeof(MyNameSpace.InvoiceMDIForm);
        case "Order":
            return typeof(MyNameSpace.OrderMDIForm);

            ...

        default:
            throw new Exception("Unknown Form Type");
    }
}
if (!FindFormWithWindowID(typeof(MyNameSpace.CustomerMDIForm), windowID))