如何避免在.NET Windows窗体中创建重复的表单?

时间:2010-06-11 13:46:48

标签: c# .net winforms menu

我正在使用.NET Windows Forms。我的MDI父表单包含菜单。如果单击菜单,将显示表单。到目前为止没有问题。

UserForm uf = new UserForm();
uf.Show();
uf.MdiParent = this;

如果再次单击该菜单,则会创建另一个表单副本。如何解决这个问题?

8 个答案:

答案 0 :(得分:5)

最简洁的方法是简单地跟踪表单实例的生命周期。通过订阅FormClosed事件来这样做。例如:

    private UserForm userFormInstance;

    private void showUserForm_Click(object sender, EventArgs e) {
        if (userFormInstance != null) {
            userFormInstance.WindowState = FormWindowState.Normal;
            userFormInstance.Focus();
        }
        else {
            userFormInstance = new UserForm();
            userFormInstance.MdiParent = this;
            userFormInstance.FormClosed += (o, ea) => userFormInstance = null;
            userFormInstance.Show();
        }
    }

答案 1 :(得分:4)

您应该创建一个 singleton 类来管理表单实例:

public class FormProvider
{
   public static UserForm UserForm
   {
       get
       {
          if (_userForm== null || _userForm.IsDisposed)
          {
            _userForm= new UserForm ();
          }
          return _userForm;
       }
   }
   private static UserForm _userForm;
}

注意,这是一个非常简单的Singleton模式。要使用该模式的正确方法,请使用此link

然后您可以按如下方式访问表单:

FormProvider.UserForm.Show();
FormProvider.UserForm.MdiParent = this;

首次访问FormProvider.UserForm时,将创建它。 FormProvider.UserForm属性上的任何后续get都将返回在首次访问时创建的表单。这意味着表单只会被创建一次。

答案 2 :(得分:4)

与此处的现有答案相反,我建议使用Singleton。 Singleton模式过度使用,通常是一种“代码味”,表明整体设计出了问题。单身人士通常与全局变量放在同一个“桶”中:你最好有一个非常强大的使用它的案例。

最简单的解决方案是在主窗体上创建一个表示相关窗体的实例变量,然后用它来显示它。

public class MainMdiForm : Form
{
    ...

    UserForm userForm;

    ...

    private void ShowUserForm()
    {
        if(userForm == null || userForm.IsDisposed)
        {
            userForm = new UserForm();
            userForm.MdiParent = this;
        }

        userForm.Show();
        userForm.BringToFront();
    }
}

答案 3 :(得分:3)

如果您知道表单的名称:

    if (Application.OpenForms["FormName"] == null)
       {
           Form form = new Form();
           form.MdiParent = this;
           form.Show();
       }
       else
           Application.OpenForms["FormName"].Focus(); 

答案 4 :(得分:0)

您可以随时将表单设为单身人士:

public class MyForm : Form
{
    private MyForm _instance = null;
    private object _lock = new object();

    private MyForm() { }


    public static MyForm Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    _instance = new MyForm();
                }
            }
            return _instance;
        }
    }
}

然后你的电话会是这样的:

MyForm.Instance.Show();
MyForm.Instance.MdiParent = this;

答案 5 :(得分:0)

选项:

通常,禁用按钮工作正常,从用户的角度来看更有意义。如果你需要为其他东西启用按钮,Singleton可以工作。

如果可以关闭表单并且以后需要新的实例,那么Singleton可能不是是一个很好的解决方案。

答案 6 :(得分:0)

您可以检查主机表单的MdiChildren属性,以确定其中是否存在UserForm的实例。

UserForm myForm = null;
foreach (Form existingForm in this.MdiChildren)
{
    myForm = existingForm as UserForm;
    if (myForm != null)
        break;
}

if (myForm == null)
{
    myForm = new UserForm();
    myForm.MdiParent = this;

    myForm.Show();
}
else
    myForm.Activate();

这将创建一个新的UserForm实例,它尚不存在,如果它存在,它将切换到创建的实例。

答案 7 :(得分:0)

这是我在ShowForm()中的解决方案,并在aboutToolStripMenuItem_Click()中调用示例:

    private void ShowForm(Type typeofForm, string sCaption)
    {
        Form fOpen = GetOpenForm(typeofForm);
        Form fNew = fOpen;
        if (fNew == null)
            fNew = (Form)CreateNewInstanceOfType(typeofForm);
        else
            if (fNew.IsDisposed)
                fNew = (Form)CreateNewInstanceOfType(typeofForm);

        if (fOpen == null)
        {
            fNew.Text = sCaption;
            fNew.ControlBox = true;
            fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            fNew.MaximizeBox = false;
            fNew.MinimizeBox = false;
            // for MdiParent
            //if (f1.MdiParent == null)
            //    f1.MdiParent = CProject.mFMain;
            fNew.StartPosition = FormStartPosition.Manual;
            fNew.Left = 0;
            fNew.Top = 0;
            ShowMsg("Ready");
        }
        fNew.Show();
        fNew.Focus();
    }
    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
        ShowForm(typeof(FAboutBox), "About");
    }

    private Form GetOpenForm(Type typeofForm)
    {
        FormCollection fc = Application.OpenForms;
        foreach (Form f1 in fc)
            if (f1.GetType() == typeofForm)
                return f1;

        return null;
    }
    private object CreateNewInstanceOfType(Type typeofAny)
    {
        return Activator.CreateInstance(typeofAny);
    }

    public void ShowMsg(string sMsg)
    {
        lblStatus.Text = sMsg;
        if (lblStatus.ForeColor != SystemColors.ControlText)
            lblStatus.ForeColor = SystemColors.ControlText;
    }
    public void ShowError(string sMsg)
    {
        lblStatus.Text = sMsg;
        if (lblStatus.ForeColor != Color.Red)
            lblStatus.ForeColor = Color.Red;
    }