Question

Is there an event I can use to tell if a child form has been added or removed from the MDI parent?

Was it helpful?

Solution

No, there is not. You would have to subclass Form and expose specific events that would indicate when the child is added and then route all attachments of child forms through a method that would wire up the child form, as well as raise the event.

OTHER TIPS

Yes. On your main MDI form, wire up to the MdiChildActivated Event.

Like so:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.MdiChildActivate += new EventHandler(Form1_MdiChildActivate);
        }

        void Form1_MdiChildActivate(object sender, EventArgs e)
        {
            MessageBox.Show("Activated");
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form form2 = new Form2();
            form2.MdiParent = this;
            form2.Show();
        }
    }

And that event will fire when the child form is both activated or deactivated.

Wire up the MdiChildActivate event and keep a list of recognized children. When a new form is activated, also wire up the FormClosed event.

private List<Form> ChildFormList = new List<Form>();

private void MyForm_MdiChildActivate(object sender, EventArgs e)
{
    Form f = this.ActiveMdiChild;

    if (f == null)
    {
        //the last child form was just closed
        return;
    }

    if (!ChildFormList.Contains(f))
    {
        //a new child form was created
        ChildFormList.Add(f);
        f.FormClosed += new FormClosedEventHandler(ChildFormClosed);
    }
    else
    {
        //activated existing form
    }
}

private void ChildFormClosed(object sender, FormClosedEventArgs e)
{
    //a child form was closed
    Form f = (Form)sender;
    ChildFormList.Remove(f);
}

I realised this is many years too late however as the answers here helped me solve this I though I would mention this works fine using the MdiChildren array in .net 4. The only thing you need to do is check if the form is disposing or disposed to tell if its closing.

ie:

    private void frmContainer_MdiChildActivate(object sender, EventArgs e)
    {
        tabWindows.RefreshLayout(this.MdiChildren.ToList());
    }

    public void RefreshLayout(List<Form> forms)
    {
        this.nextButtonLeft = 1;
        panel1.Controls.Clear();
        foreach (Form frm in forms)
        {
            if (!(frm.Disposing || frm.IsDisposed)) { addButton(frm); }
        }
    }

Yes, you can easily detect the forms adding in MDI Form.

When mark the ParentForm as MdiContainer by setting the IsMdiContainer to true, the ParentForm.ControlAdded event raised for adding the "MdiClient" control to the parent form. So when adding MdiClient to parent MDI form, we can raise the ControlAdded event for the MdiClient control as like below,

  public ParentForm()
  {
    InitializeComponent();
    this.ControlAdded += Form1_ControlAdded;
    this.IsMdiContainer = true;

We need to raise the MdiClient.ControlAdded as like the below,

    void Form1_ControlAdded(object sender, ControlEventArgs e)
      {
           if(e.Control is MdiClient)
                e.Control.ControlAdded += MdiClient_ControlAdded;

      }

By default the MDI Child forms are added into the controls collection of the MdiClient in Parent form. So when set the ChildForm.MdiParent value as Parent form, the ControlAdded event for the MdiClient will raise.

void MdiClient_ControlAdded(object sender, ControlEventArgs e)
{

}

So by using the above method, you can know the child MDI forms added into the parent MDI forms. Like this you can add the ControlRemoved event for the MdiClient control to know the child forms removed from MDI form.

Hope this will help you.

private void closeToolStripMenuItem1_Click(object sender, EventArgs e)
    {
      List<Form> fm = this.MdiChildren.ToList();
        if(fm!=null && fm.Count>0)
        {
            foreach(Form lfm in fm)
            {
                lfm.Close();
            }
        }
    }

Since the MdiChildActivate event is fired before the MDI child form is actually closed and therefore there isn't enough information to detect if a MDI child form is actually activated or closed, I chose a different approach to solve the problem.

I found that the ParentChanged event fires on the MDI child form when it is closed.

public class MdiParentForm : Form
{
    // ...

    private Form CreateMdiChildForm()
    {
        var form = new MdiChildForm
        form.ParentChanged += MdiFormParentChangedHandler;
        form.MdiParent = this;
        return form;
    }

    private void MdiFormParentChangedHandler(object sender, EventArgs args)
    {
        var form = sender as Form;
        if (form != null)
        {
            if (form.MdiParent != null)
            {
                // MDI child form will activate
                // ... your code here
            }
            else
            {
                // MDI child form will close
                form.ParentChanged -= MdiFormParentChangedHandler;
                // ... your code here
            }
        }
    }

    // ...
}

I recently wanted to determine approximately when there were NO MDIchildren open so I could display a panel with lots of "things to do" buttons on it Only when there were no child forms open. (just exploring a design idea).

My eventual solution was elegantly simple - add a timer to the parent form and start the timer up whenever the MdiChildActivate event determined there was 1 child form open.

    private void MyForm_MdiChildActivate(object sender, EventArgs e)
    {
        this.panel_Tools.Visible = false;
        if (this.MdiChildren.Count() == 1)
        {
            this.timer_WindowsCounter.Start();
        }
        else
        {
            this.timer_WindowsCounter.Stop();
        }

    }


    private void timer_WindowsCounter_Tick(object sender, EventArgs e)
    {
        if (this.MdiChildren.Count() == 0)
        {
            this.panel_Tools.Visible = true;
            this.timer_WindowsCounter.Stop();
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top