Search code examples
c#winformseventsmdi

How do I respond to the last MDI childform closing?


My goal is to respond to the last child form of an mdi container closing(for example, close the parent itself or show something new). The problem I face is that the mdi container's MdiChildren collection still indicates that the container contains children.

The approach I have tried is

void childMdiForm_FormClosed(object sender, FormClosedEventArgs e)
{
    if (this.MdiChildren.Any())
    {
        //Do stuff
    }
}

MdiChildren.Count() is still 1 after the last child form is closed.

I have the same results by trying to handle the parentform.MdiChildActivate event.

The MdiChildren collection appears to not be updated yet when the child form has closed. The same occurs when there are multiple children: it will still contain all the crildren, it appears to update the collection at a later moment.

Is this the right approach? If not, how can I get an accurate count of the number of mdi children after closing a form?


Solution

  • WinForms can be a little quirky at times and this is one example of that. I am not entirely sure why closing the last MDI child does not make the MdiChildren property return an empty array immediately thereafter.

    In most cases you're going to be keeping track of either the children forms or the data models yourself, so I would simply keep a local array for managing this:

        List<Form> childForms = new List<Form>();
    
        void AddChildWindow()
        {
            var window = new ChildForm();
            window.MdiParent = this;
            window.Tag = Guid.NewGuid();
    
            window.FormClosed += (sender, e) => { OnMdiChildClosed(sender as Form, e.CloseReason); };
            window.Shown += (sender, e) => { OnMdiChildShown(sender as Form); };
    
            window.Show();
        }
    
        void OnMdiChildShown(Form window)
        {
            childForms.Add(window);
    
            Trace.WriteLine(string.Format("Child form shown: {0}", window.Tag));
            Trace.WriteLine(string.Format("Number of MDI children: {0}", childForms.Count));
        }
    
        void OnMdiChildClosed(Form window, CloseReason reason)
        {
            childForms.Remove(window);
    
            Trace.WriteLine(string.Format("Child form closed: {0} (reason: {1})", window.Tag, reason));
            Trace.WriteLine(string.Format("Number of MDI children: {0}", childForms.Count));
    
            if (childForms.Count == 0)
            {
                 // Do your logic here.
            }
        }