一次只打开一个子窗体的实例c#

Posted

技术标签:

【中文标题】一次只打开一个子窗体的实例c#【英文标题】:Have only one instance of a subform open at a time c# 【发布时间】:2013-01-19 19:23:17 【问题描述】:

我正在编写一个应用程序,该应用程序使用一系列类似向导的 5 个简单表单。第一个表单 NewProfile 是从主应用程序 MainForm 上的菜单项打开的,MainForm 的子表单也是如此。第二种形式,TwoProfile,是从 NewProfile 上的一个按钮打开的。第三种形式,ThreeProfile 是从 TwoProfile 上的一个按钮打开的,对于所有 5 个形式,依此类推。这是顺序: MainForm --> NewProfile TwoProfile ThreeProfile FourProfile FiveProfile。我的问题是,当打开任何表单(NewProfile、TwoProfile、ThreeProfile、FourProfile 或 FiveProfile)时,我不希望用户能够创建 NewProfile 的实例。

我从实现一个单例模式开始,它在中途工作。如果 NewProfile 打开并且我转到 MainForm 并尝试创建另一个 NewProfile 实例,它就可以工作。如果 NewProfile 已被破坏,则它不起作用,通过前进到下一个表单并且 TwoProfile、ThreeProfile、FourProfile 或 FiveProfile 之一打开。它告诉我 NewProfile.IsDisposed 是真的,给了我对 Singleton 实例的错误引用。

我想不通的是如何执行我的逻辑,以便在 TwoProfile、ThreeProfile、FourProfile 或 FiveProfile 之一打开或 NewProfile 本身打开时不会创建 NewProfile。

我希望这是有道理的。除了我为 Singleton 所做的之外,我真的没有太多代码要发布。

   private static NewProfile _instance = null;
   public static NewProfile Instance
    
        get
        
            if (_instance == null)
            
                _instance = new NewProfile();
            
            return _instance
        
    

谢谢你:)

【问题讨论】:

你为什么不只使用一个包含用户控件的表单,而只是更改主窗体中的用户控件,这将确保你只打开“一个”表单并且所有用户控件都存储在列表中以及您可以处理加载哪个 UC 的 Next 或 Back 按钮 您能否在打开 SecondProfile 时简单地隐藏() NewProfile 而不是销毁它? 你有没有看过做 MDI..? 【参考方案1】:

正如 cmets 中所建议的,每个“表单”实际上都可以是您交换的用户控件。这样,您只有一个表单和多个页面。或者,您可以隐藏表单。

如果您想要多个表单,那么您可以遍历所有打开的表单并查看您要检查的表单是否打开。如果没有,你可以打开NewProfile

bool shouldOpenNewDialog = true;

foreach (Form f in Application.OpenForms)
       
    //give each dialog a Tag value of "opened" (or whatever name)
    if (f.Tag.ToString() == "opened")
        shouldOpenNewDialog = false;    



if(shouldOpenNewDialog)
    np = new NewProfile();

它未经测试,但它应该遍历所有打开的表单并查找任何有Tagopened 的表单。如果遇到一个,则将 shouldOpenNewDialog 标志设置为 false 并且不会调用 NewProfile

【讨论】:

感谢您的及时回复!我在表格上付出了很多努力,所以我真的不想做大量的返工。最终起作用的是keyboardP建议的变体。我在 MainForm 菜单项处理程序中这样做了: 哎呀,我的意思是转到下一行...呵呵。 if (Application.OpenForms.Count > 1) shouldOpenDialog = false; if (shouldOpenDialog) newProfile.Show(); 随时发布您的最终代码作为答案,然后在几天后接受它:)【参考方案2】:

我们处理这个问题的方法是使用一个静态窗口管理器类来跟踪打开的表单实例。当用户执行会导致打开新窗口的操作时,我们首先检查窗口管理器以查看表单是否已打开。如果是,我们将重点放在它上,而不是创建一个新实例。

每个打开的表单都继承自一个基本表单实现,该实现在打开时自动向窗口管理器注册,并在关闭时删除其注册。

这里是 WindowManager 类的大致轮廓:

public class WindowManager

    private static Dictionary<string, Form> m_cOpenForms = new Dictionary<string, Form>();

    public static Form GetOpenForm(string sKey)
    
        if (m_cOpenForms.ContainsKey(sKey))
        
            return m_cOpenForms[sKey];
        
        else
        
            return null;
        
    
    public static void RegisterForm(Form oForm)
    
        m_cOpenForms.Add(GetFormKey(oForm), oForm);
        oForm.FormClosed += FormClosed;
    

    private static void FormClosed(object sender, FormClosedEventArgs e)
    
        Form oForm = (Form)sender;
        oForm.FormClosed -= FormClosed;
        m_cOpenForms.Remove(GetFormKey(oForm);
    

    private static string GetFormKey(Form oForm)
    
        return oForm.Name;
    

你可以按如下方式使用它:

        Form oForm = WindowManager.GetOpenForm("Form1");
        if (oForm != null)
        
            oForm.Focus();
            oForm.BringToFront();
        
        else
        
            oForm = new Form1();
            WindowManager.RegisterForm(oForm);
            // Open the form, etc
        

【讨论】:

以上是关于一次只打开一个子窗体的实例c#的主要内容,如果未能解决你的问题,请参考以下文章

c#子窗体控制父窗体的显隐

delphi平台,在一个主窗体上打开两个子窗体,也就是:打开一个子窗体之后,再打开第二个窗体第一个窗体不关闭

mmenu: 一次只展开一个子菜单 (slidingSubmenus: false)

C#多文档程序中如何只打开一个子窗口

C#做winform时,登录系统后怎么写判断一个子窗体的文本框中输入的密码是不是与当前登录的密码一致?

c#WinForm窗体限制只能打开一次