Hash

March 31, 2009

C# Winforms: Create a Single Instance Form Using Singleton

A common practice in WinForms programming is to keep only one instance of a certain form in the application. A new instance of that form is never created and shown. I have previously written a small note on this topic and gave a solution here which I personally don’t like.

In this post I am presenting a much better solution which is based on the singleton pattern. Rather than each time looking for the form in a list of opened forms I make the constructor private.

Let us start with the Form:

public sealed partial class ThirdForm : Form
{

}

The class is sealed so it cannot be inherited. We don’t want a child create an instance of this class multiple times.

Now add these members and methods to the class:

private static readonly ThirdForm MyInstance = new ThirdForm();

This is the sole instance of this form. And the private constructor to avoid multiple instances outside the class:

private ThirdForm()
{
    InitializeComponent();
}

And the property to publish the sole instance:

public static ThirdForm OnlyInstance
{
    get { return MyInstance; }
}

Another functionality that you might want to add to your Form is a new Show method. And you may also want to know whether the form was already opened or your opened it. Here is the answer to these questions. Add this code to your form class to Show() or Select() if already shown.

public new void Show()
{
    if (IsShown)
        base.Show();
    else
    {
        base.Show();
        IsShown = true;
    }
}

A variable IsShown of type bool is added to the form to record the current state.

private static bool IsShown = false;

static ThirdForm()
{
    OnlyInstance.FormClosing += new FormClosingEventHandler(OnlyInstance_FormClosing);
}

private static void OnlyInstance_FormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = true;
    IsShown = false;

    OnlyInstance.Hide();
}

The variable IsShown is set to false when the only instance of this form is closed. But remember its a singleton. We can’t let the only instance die so we catch FormClosing event and Hide() the form instead of closing it.

This solution looks elegant than looking for an opened form in an array but it has draw backs. You cannot catch the FormClosed event because it will never happen. The form is created only once so if your form is based on some volatile objects you will never see the change even if you close and open it again. May be I try to address these problems in another post some day. Spot On!

Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!
About these ads

8 Comments »

  1. Pretty cool Joel. In your “Show” function, did you mean to put “base.Select()” instead of “base.Show()” if the form is already shown?

    Comment by Brett — April 16, 2009 @ 12:50 am

  2. Oh you right mate :) but I reckon thats trivial.

    Comment by hashfactor — April 16, 2009 @ 12:57 am

  3. hi!
    Your post was very useful!
    i’m not that good at c#.
    I did everything as you said, but how can I show this form from another form? i have addItem form.
    i used addItem.show();
    but it shows up Error message: ‘iLib.addItem.addItem()’ is inaccessible due to its protection level

    Comment by ganni — April 20, 2009 @ 5:27 pm

  4. I see you are calling from a different namespace. Make your form public so it can be accessible from other namespaces.

    Comment by hashfactor — April 20, 2009 @ 6:30 pm

  5. Thank you! Hash!

    but i still couldn’t get what was the problem.
    ThirdForm.cs
    namespace WindowsFormsApplication1
    {

    public sealed partial class ThirdForm : Form
    {
    private static readonly ThirdForm MyInstance = new ThirdForm();
    private ThirdForm()
    {
    InitializeComponent();
    }
    public static ThirdForm OnlyInstance
    {
    get { return MyInstance; }
    }
    public new void Show()
    {
    if (IsShown)
    base.Show();
    else
    {
    base.Show();
    IsShown = true;
    }
    }
    private static bool IsShown = false;

    static ThirdForm()
    {
    OnlyInstance.FormClosing += new FormClosingEventHandler(OnlyInstance_FormClosing);
    }

    private static void OnlyInstance_FormClosing(object sender, FormClosingEventArgs e)
    {
    e.Cancel = true;
    IsShown = false;

    OnlyInstance.Hide();
    }
    }

    }

    form1.cs
    namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    ThirdForm third = new ThirdForm();
    third.Show();
    }
    }
    }

    when I run this this gives the same error message.
    can you tell me what’s wrong? please!

    Thank you

    Comment by ganni — April 20, 2009 @ 6:44 pm

  6. Aaah now I get it.

    ThirdForm is supposed to throw this error. It is programmed like that purposefully.

    Use ThirdForm like this.

    ThirdForm third = ThirdForm.OnlyInstance;
    third.show();

    Comment by hashfactor — April 20, 2009 @ 7:57 pm

  7. yeah!!!!!! that works
    Thank you! Hash! You made my day!!! Hooray!!!
    :))

    thanks!

    Comment by ganni — April 20, 2009 @ 8:03 pm

  8. you were a great help thanx

    Comment by Shlomo — November 25, 2009 @ 7:44 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: