Saturday, April 14, 2012

Forms Handler

I frequently see forum questions about how to handle/manage an app that uses many Windows Forms (when you’re not using MDI forms). It’s pretty simple really if you use a custom FormsHandler. This is something I wrote years ago and it still works just fine. It could probably stand to be updated a bit, like instead of using an ArrayList, use a List<Form> … but I’ll leave that as an exercise for the reader.

First the FormsHandler class. Notice that it uses only static methods, so the class never needs to be instantiated.

using System;
using System.Collections;
using System.Windows.Forms;

namespace MyNameSpace.MyClasses
{
    public class FormsHandler
    {
        #region Declarations
        private static ArrayList list = new ArrayList();
        #endregion

        #region Methods
        public static void Add(Form o)
        {
            Form oForm = Find(o);
            if (oForm == null)
            {
                oForm = o;
                list.Add(o);
            }

            oForm.Show();
        }
        public static Form Find(Form o)
        {
            foreach (Form x in list)
            {
                if (o.GetType().Equals(x.GetType()))
                    return x;
            }
            return null;
        }
        public static void Remove(object o)
        {
            list.Remove(o);
        }
        public static bool Close()
        {
            int nCount = list.Count;
            while (list.Count > 0)
            {
                ((Form)list[0]).Close();
                if (list.Count == nCount)
                    return false;
                else
                    nCount = list.Count;
            }

            return true;
        }
        #endregion

        #region Properties
        public static ArrayList List
        {
            get { return list; }
        }
        #endregion
    }
}

Whenever you open a form, no matter where you open it from, all you do is add it to the ArrayList, like this:

Form oForm = new MyForm();
FormsHandler.Add(oForm);

All your Forms should have this in their ClosedHandler() method:

protected virtual void ClosedHandler(object sender, EventArgs e)
{
    FormsHandler.Remove(this);
}

When you close your Main Form, you want all others to Close (but to execute their own Closing methods) ... do it like this:

// This is a menu item that exits the application

private void menuItem4_Click(object sender, System.EventArgs e)
{
    System.ComponentModel.CancelEventArgs ee = new CancelEventArgs();
    this.ClosingHandler(sender, ee);
}

// This is the ClosingHandler that will execute normally if you close the app
// by clicking on the "X"

private void ClosingHandler(object sender, System.ComponentModel.CancelEventArgs e)
{
    if (!FormsHandler.Close())
        e.Cancel = true;
    else
        Application.Exit();
}

Notice that the FormsHandler.Close() method will iterate through each Form contained in its list and attempt to close that Form. If it can successfully close all the Forms, then it will return true, otherwise it will return false.