How to avoid Multiple Child forms shown in MDIParent C# Win Forms
Asked Answered
B

15

8

I want to avoid my child form from appearing many times when a user tries to open the child form which is already open in MDIParent. One way to avoid this is by disabling the Controller (in my case BUTTON) but I have given a shortcut key (Ctrl+L) for this function as well. So if the user types Ctrl+L, the same child Form opens and I can see two child forms are in MDI.

private void leadsToolStripMenuItem_Click(object sender, EventArgs e)
    {
        frmWebLeads formWeblead = new frmWebLeads();
        formWeblead.MdiParent = this;
        formWeblead.WindowState = System.Windows.Forms.FormWindowState.Maximized;
        formWeblead.Show();

    }

I want to avoid this. How can I do this? enter image description here

In the image you can see that a child form Name Online Leads is opened twice as the user opened first time using Menu (LEADS) and second time by Shortcut key. I don't want this to happen. If the form is already opened it should avoid opening another same form ... How to do this?

Bradybradycardia answered 12/7, 2011 at 4:16 Comment(0)
S
4

the way i usually do it if i am only supposed to have one open is something like:

//class member for the only formWeblead
frmWebLeads formWebLead = null;

private void leadsToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (formWebLead == null)
    {
        formWeblead = new frmWebLeads();
        formWeblead.MdiParent = this;
    }

    formWeblead.WindowState = System.Windows.Forms.FormWindowState.Maximized;
    formWeblead.Show();
}
Salinasalinas answered 12/7, 2011 at 4:37 Comment(0)
A
4

Set this in your form main() function

    InitializeComponent();
     this.WindowState = FormWindowState.Maximized;
     this.ShowInTaskbar = true;

 from_login login = new from_login();
                login.MdiParent=this;
                login.Show();
                pmsnrr.pmsmain = this;  

and this is the code the goes inside your menu strip slick event

if (this.ActiveMdiChild != null)
            this.ActiveMdiChild.Close();
            frm_companymaster company = new frm_companymaster();
            company.MdiParent = this;
            company.WindowState = FormWindowState.Normal;
            company.Show();
Ashram answered 10/11, 2012 at 8:9 Comment(0)
A
4

I personally prefer a generic implementation:

private void ShowOrActivateForm<T>() where T : Form
        {
            var k = MdiChildren.Where(c => c.GetType() == typeof(T)).FirstOrDefault();
            if (k == null) 
            {                    

                k = (Form)Activator.CreateInstance(typeof(T));
                k.MdiParent = this;
                k.Show();
            }
            else
            {
                k.Activate();                
            }            
        }

Then you can just use it like this:

ShowOrActivateForm<myForm>();

Where myForm is the TYPE of the form you want to create

Adore answered 5/8, 2014 at 6:27 Comment(4)
I like this approach. It's much more scalable than creating empty fields for each child. +1 for generics. I'd be interested to know if there's any noticable additional overhead for the use of reflection; albeit at a very high level.Armalla
I'd imagine any additional overhead would be negligible. It only runs when you try and open a form, so unless you are opening tons of forms at once I can't imagine it would have any impact on your application performance or user experience.Adore
That's good. I suppose in a scalable application, you'd use your IoC Container anyway, instead of relying on the Activator. I've used this method with RadDock now, to keep track of MDI Children, and Tool Windows. I've taken the Show() and Activate() out, and returned the raw form as type T, so that it can be docked where needed.Armalla
Nice. Cool solution. Thanks for the feedback. Glad I could share something that someone else could use :)Adore
G
3
private void leadsToolStripMenuItem_Click(object sender, EventArgs e)
{
    formWeblead formWeblead = null;
    if ((formWeblead = IsFormAlreadyOpen(typeof(frmWebLeads)) == null)
    {
        formWeblead = new frmWebLeads();
        formWeblead.MdiParent = this;
        formWeblead.WindowState = System.Windows.Forms.FormWindowState.Maximized;
        formWeblead.Show();
    }
}

public static Form IsFormAlreadyOpen(Type FormType)
{
   foreach (Form OpenForm in Application.OpenForms)
   {
      if (OpenForm.GetType() == FormType)
         return OpenForm;
   }

   return null;
}
Gabfest answered 12/7, 2011 at 4:40 Comment(2)
I'm sorry, but I don't have that same issue. I'm running .NET 3.5 on VS 2008. I can close and open only one form repeatedly.Gabfest
i am using .net 3.5 and VS 2010 Ultimate ,Windows Xp ..is this cousing errorBradybradycardia
C
3
    frmWebLeads formWeblead;

    bool isformWebleadOpen =false;

    private void leadsToolStripMenuItem_Click(object sender, EventArgs e)
    {
      if(isformWebleadOpen == false)
      {
       formWeblead = new frmWebLeads();
       isformWebleadOpen =true;
       formWeblead.Closed += formWeblead_Closed;
       formWeblead.Show();
      }
   }

   void formWeblead_Closed(object sender, EventArgs e)
   {
     isformWebleadOpen = false;
   }
Crymotherapy answered 22/2, 2014 at 8:58 Comment(0)
R
1

Fists time when you open the form from menu, the variable frmRep is null

frmReportes frmRep = null

...so I add another "if" inside the first "if" to validate my form is visible, because I have another forms, then if its not visible I make an instance and show the form, but if is visible I just use Activate()

    private void rToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (frmRep != null)
        {
            if (frmRep.Visible == false)
            {
                frmRep = new frmReportes();
                frmRep.MdiParent = this; frmRep.Show();
            }
            else
            {                    
                frmRep.Activate();
                return;
            }
        }
        else
        {
            frmRep = new frmReportes();
            frmRep.MdiParent = this; 
            frmRep.Show();
        }            
    }
Ruddock answered 4/5, 2016 at 18:28 Comment(0)
L
0

The easiest way is to keep a reference to the child form, and only spawn a new one if it doesn't already exist. Something like this:

class ParentForm : Form { 
    frmWebLeads formWeblead = null;

    //...

    private void leadsToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if(formWeblead != null) return;
        formWeblead = new frmWebLeads();
        formWeblead.MdiParent = this;
        formWeblead.WindowState = System.Windows.Forms.FormWindowState.Maximized;
        formWeblead.Show();

    }

}

You also need code to set formWeblead to null when you close it, but I'm sure you can figure that part out :)

Legalize answered 12/7, 2011 at 4:38 Comment(4)
@ Mike Caron thanks for your Code. The Last Part you left for me creating some confusion, have doubt in that the declared formWeblead i n MDIParent and i thinking to set formWeblead =null using frmWebLoad leaving Event using Child to parent access ,is it fine !! ??? or is there any best method availableBradybradycardia
I don't think I would use the Leaving event, as that's a focus thing. Instead, using the child form's Closing event, which triggers when you close it.Legalize
@Mike This leaves some TODO regarding the menu item that calls the click event; I like to disable the menu item that created the form to avoid confusion to the user e.g. "I am clicking 'open' and nothing happens".Backblocks
@Gangelo: Well, sure. But that's outside the scope of the question. It's not hard to figure out where to insert the .Enabled = false and .Enabled = true code. Or, even better, the formWeblead.Focus() code.Legalize
B
0
// Implementation of the below class in your MDI Parent
private void openToolStripMenuItem_Click(object sender, EventArgs e) {
            if (SingletonForm.Exists) {
                return;
            } else {
                m_openToolStripMenuItem.Enabled = false;

                SingletonForm form = new SingletonForm();
                form.FormClosed += new FormClosedEventHandler(
                    delegate(object _sender, FormClosedEventArgs _e) {
                        m_openToolStripMenuItem.Enabled = true;
                    });
                form.MdiParent = this;              
                form.Show();
            }
        }


// SingletonForm Class
    using ...
    using System.Threading;

    namespace SingletonForm {

        public partial class SingletonForm : Form, IDisposable {
            static private readonly string m_mutexName = "SingletonForm.SingletonForm";
            private Mutex m_mutex;
            private bool m_disposed;

            public SingletonForm() {
                m_disposed = false;

                // Check to see if there is already a running instance...
                bool owned;
                m_mutex = new Mutex(true, m_mutexName, out owned);
                if (!owned) {
                    // Already running, get out...
                    Close();
                    return;
                }

                InitializeComponent();
            }

            ~SingletonForm() {
                Dispose(false);
            }

            static public bool Exists {
                get {
                    bool owned;
                    using (new Mutex(false, m_mutexName, out owned)) {
                        return !owned;
                    }
                }
            }

            // IDisposable Members
            // --------------------------------------------------------------------------
            #region IDisposable Members
            new public void Dispose() {
                Dispose(true);

                // Use SupressFinalize in case a subclass of this type implements a finalizer.
                GC.SuppressFinalize(this);
            }
            #endregion  // IDisposable Members

            /// <summary>
            /// Note: Comment out the Dispose(bool disposing) implementation in your
            /// SingletonForm.Designer.cs
            /// </summary>
            /// <param name="disposing">true if we are disposing.</param>
            protected override void Dispose(bool disposing) {
                if (disposing && (components != null)) {
                    components.Dispose();
                }

                base.Dispose(disposing);

                // If you need thread safety, use a lock around these 
                // operations, as well as in your methods that use the resource.
                if (!m_disposed) {
                    if (disposing) {
                        // Code to dispose the managed resources held by the class here...
                        if (m_mutex != null) {
                            m_mutex.Dispose();
                            m_mutex = null;
                        }
                    }

                    // Indicate that the instance has been disposed.
                    m_disposed = true;
                }
            }
        };
    };

Would have been nice to use semaphores instead in order to allow 1-n instances to exist.

Backblocks answered 12/7, 2011 at 13:3 Comment(0)
R
0

Here is the "Method" that I created for Calling open only one form when u click on Menu in MDIParent. Hope this "Method" can help you!

Usage: On Even ToolStripMenuItems.

Form1 frm1 = new Form1();
CheckActiveChildForm(frm1,"myForm");

//myForm is the Text of Form1
private void CheckActiveChildForm(Form FormControl, string FormExists)
{
    int h = 0;
    if (MdiChildren.Count() == 0)
    {
        //Form2 childF = new Form2();
        FormControl.MdiParent = this;
        FormControl.Show();
    }

    if (MdiChildren.Count() > 0)
    {
        for (int i = 0; i < MdiChildren.Count(); i++)
        {
            if (MdiChildren.ElementAt(i).Text == FormExists)
            {
                h = 1;
            }
        }
    }

    if (h == 0)
    {
        FormControl.MdiParent = this;
        FormControl.Show();
    }
}
Rosenkrantz answered 21/2, 2012 at 2:16 Comment(0)
R
0

You could check current open forms to achieve that:

if (Application.OpenForms.Count == 1) {
    ReportProductDetails Report9 = new ReportProductDetails();
    Report9.MdiParent = this;
    Report9.Show();
    Report9.Activate();
}
else {
    MessageBox.Show("Sorry!Close the All the Exist Form,Before open this Form", "Information", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Regulation answered 16/12, 2012 at 9:13 Comment(0)
M
0

I use this solution, with a little trick

frmWebLeads formWebLead = null;

private void leadsToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (formWebLead == null || formWebLead.isAccessible == false)
        {
            formWeblead = new frmWebLeads();
            formWeblead.MdiParent = this;
        }

        formWeblead.WindowState = System.Windows.Forms.FormWindowState.Maximized;
        formWeblead.Show();
    }
Mairamaire answered 22/4, 2013 at 9:24 Comment(0)
F
0

The code which prevents the same child form in an MDI form

private void materialToolStripMenuItem_Click(object sender, EventArgs e)
{
  frmMaterial newMDIChild = new frmMaterial();
  bool opened = false;
  foreach (Form OpenForm in Application.OpenForms)
  {
    if (OpenForm.GetType() == typeof(frmMaterial))
    {
      OpenForm.Activate();//to bring the activated form to the front
      opened = true;
    }
  }
  if (opened==false)
  {
    // Set the Parent Form of the Child window.
    newMDIChild.MdiParent = this;
    //newMDIChild.WindowState = System.Windows.Forms.FormWindowState.Maximized;
    // Display the new form.
    newMDIChild.Show();
  }
}
Fremitus answered 17/12, 2015 at 10:36 Comment(0)
B
0
    private void mnuMyForm_Click(object sender, EventArgs e) // click to open MyForm
    {
        foreach (Form item in this.MdiChildren) // check all opened forms
        {
            if (item.Name == "MyFormName") // check by form name if it's opened
            {
                item.BringToFront(); // bring it front
                return; //exit
            }
        }

        // if MyForm is not opened
        // you know what it is
        MyForm frm = new MyForm();
        frm.MdiParent = this;
        frm.Show();
    }
Beriberi answered 20/12, 2015 at 13:30 Comment(0)
G
0

the simpleist ways of preventing multiple instance of child

private void Showforms(Form frm)
{
    if (this.ActiveMdiChild==null)
    {
        frm.MdiParent = this;
        frm.Show();
    }  
}
Gerson answered 9/8, 2016 at 2:53 Comment(0)
G
0

The simplest ways of preventing multiple instance of child:

 private void Showforms(Form frm)
 {
   if (this.ActiveMdiChild==null)
   {
      frm.MdiParent = this;               
      frm.Show();
   }
 }

Then call it like this:

Form1 frm = new Form1();
Showforms(frm);
Gerson answered 9/8, 2016 at 3:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.