Ayyappan Anbalagan
Ayyappan Anbalagan

Reputation: 11302

How to avoid duplicate form creation in .NET Windows Forms?

I am using .NET Windows Forms. My MDI parent form contains the menu. If click the menu the form will be displayed. Up to now no problem.

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

If I click the menu again another duplicate of the form is created. How to solve this issue?

Upvotes: 4

Views: 6605

Answers (8)

user2329135
user2329135

Reputation: 1

This is my solution in ShowForm() and calling sample in 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;
    }

Upvotes: 0

IgorOliveira
IgorOliveira

Reputation: 1659

If you know the name of the form :

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

Upvotes: 3

Adam Robinson
Adam Robinson

Reputation: 185643

In contrast to the existing answers here, I would not recommend using a Singleton for this. The Singleton pattern is woefully overused, and is generally a "code smell" that indicates that something's gone wrong with your overall design. Singletons are generally put in the same "bucket" as global variables: you'd better have a really strong case for using it.

The simplest solution is to make an instance variable on your main form that represents the form in question, then use that to show it.

public class MainMdiForm : Form
{
    ...

    UserForm userForm;

    ...

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

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

Upvotes: 4

Hans Passant
Hans Passant

Reputation: 941485

The cleanest way is to simply track the lifetime of the form instance. Do so by subscribing the FormClosed event. For example:

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

Upvotes: 5

djdd87
djdd87

Reputation: 68466

You should create a singleton class for managing your form instances:

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

NB, this is a very simple Singleton pattern. For the correct way to use the pattern, use this link.

You can then just access the form as follows:

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

When FormProvider.UserForm is accessed for the FIRST time, it will be created. Any subsequent get on the FormProvider.UserForm property will return the form that was created on first access. This means that the form will only ever be created once.

Upvotes: 4

Nathen Silver
Nathen Silver

Reputation: 439

You could just examine the MdiChildren property of your host form to determine if an instance of your UserForm exists in it.

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

This will create a new instance of your UserForm is it doesn't already exist, and it will switch to the created instance if it does exist.

Upvotes: 0

Justin Niessner
Justin Niessner

Reputation: 245429

You could always make the Form a Singleton:

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

Then your call would look something like:

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

Upvotes: 0

Jay
Jay

Reputation: 57919

Options:

Typically, disabling the button works fine, and makes more sense from the user's perspective. Singleton works if you need the button enabled for something else.

Singleton is probably not a good solution if the form could be closed and a new instance will later be required.

Upvotes: 0

Related Questions