Results 1 to 1 of 1

Thread: [2005] Generic Singleton Form (Maintaining Only One Instance of a Form)

  1. #1

    Thread Starter
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    [2005] Generic Singleton Form (Maintaining Only One Instance of a Form)

    VB Version Here

    Please see note at the bottom of the post.

    Often times you want to ensure that you only have one instance of a particular type of form. This is probably most common with MDI child forms, where you only want to have one instance of a child form even if the user tries to open it more than once from a button or menu item. I've often advised people to implement the Singleton pattern for that form but it's a bit cumbersome doing that every time. I always though generics should be able to help but never looked into it any further. I needed this feature myself just recently so I did look further and here's what I came up with:
    csharp Code:
    1. public class FormSingleton<TForm> where TForm : Form, new()
    2.     {
    3.         private static TForm _instance;
    4.  
    5.         public static TForm Form
    6.         {
    7.             get
    8.             {
    9.                 if (_instance == null || _instance.IsDisposed)
    10.                 {
    11.                     _instance = new TForm();
    12.                 }
    13.                 return _instance;
    14.             }
    15.         }
    16.  
    17.         public static void Show()
    18.         {
    19.             //Ensure the form is visible and has focus.
    20.             Form.Show();
    21.             Form.Activate();
    22.         }
    23.        
    24.     }

    This is the interesting part here:

    Code:
    public class FormSingleton<TForm> where TForm : Form, new()
    Many people will have used generics before but may not have declared their own. The underlined part is what makes the class generic. You specify a type for the TForm parameter when you create an instance and everywhere TForm appears in the code is then "replaced" with that type. For instance, if you do this:

    csharp Code:
    1. FormSingleton<Form1> f1 = new FormSingleton<Form1>();

    that fixes the _form variable and Form property to type Form1.

    The part that is probably unfamiliar to almost everyone is the bold bit. You can constrain generic parameters to allow yourself to treat them in certain ways within the code. For instance, I've specified that TForm must be type Form or a type derived from Form. That allows me to access members of the Form class, e.g. IsDisposed, within that code via a variable of type TForm. That's because we're guaranteed that no matter what type it is those members will be present.

    I've also added a New constraint, which means that the type must have an accessible constructor with no arguments. That's what allows me to create an instance inside the Form property getter. Without that constraint I would not be guaranteed of being able to create an instance like that so the compiler wouldn't let me.

    Now, how do you use it? All you need is one line of code:

    csharp Code:
    1. FormSingleton<MyForm>.Show();

    where MyForm is the type of form you want to display. That will create an instance of MyForm class if one doesn't already exist, then display and focus the one instance of the class. You can just call that one line of code over and over and you'll never get a second instance. If an instance already exists it will simply take focus.

    If you want to use this for MDI child forms you have set the MdiParent property of the class's Form property too, or you could extend the class like this:

    csharp Code:
    1. public class MdiFormSingleton<TForm> : FormSingleton<TForm> where TForm : Form, new()
    2.     {
    3.         public static void ShowChild(Form mdiParent)
    4.         {
    5.             {
    6.                 Form.MdiParent = mdiParent;
    7.                 Form.Show();
    8.                 Form.Activate();
    9.             }
    10.         }
    11.     }

    Now your code to show the form becomes:

    csharp Code:
    1. MdiFormSingleton<MyForm>.ShowChild(this);

    Note: I do not take credit for this code nor the explanation as this has been submitted by jmcilhinny. This is merely the C# equivalent of his valuable VB post of which the link can be found at the top.
    Last edited by ForumAccount; May 22nd, 2009 at 08:39 AM. Reason: Fixed underlining

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width