SQL Police
SQL Police

Reputation: 4206

Singleton form: how to handle the case when form is "disposed"

I want to implement a "Popup" information form, which should be shown at various occasions (like mouse over, context menu, etc), and which should automatically hide when the user changes the focus.

I decided to do it with the SINGLETON pattern, like this:

public class frmCellInfo : Form
{
    public static frmCellInfo instance; 

    public static frmCellInfo GetInstance()
    {
        if (instance == null)
            instance = new frmCellInfo();
        return instance;
    }

    private frmCellInfo() // PRIVATE, because of Singleton
    {
         InitializeComponent();
    }

    private void frmCellInfo_Deactivate(object sender, EventArgs e)
    {
        this.Hide();
    }

    // ......

The form is called like this:

frmCellInfo frm = frmCellInfo.GetInstance();
frm.Show();

Basically, the automatic show/hide works like intended; however, when the user CLOSES the form by clicking the "X" icon, then the form goes, and next time, when I try to acces the form, I get the exception "Cannot access a disposed object"

So in way, the instance is still "there", but "disposed" (?)

Question: How should I rewrite the call of the form or the singleton pattern, so that in case the form is "disposed", I can create it again?

Upvotes: 3

Views: 1575

Answers (3)

Fabio
Fabio

Reputation: 32445

Your reference frmCellInfo.instance is not null,
when you tried to open form after it was closed by X button (Disposed)

Then method frmCellInfo.GetInstance() return reference to the disposed instance.

Set it to null in the FormClosed eventhandler

private void frmCellInfo_FormClosed(object sender, FormClosedEventArgs e)
{
    frmCellInfo.instance = null;
}

Then in the method frmCellInfo.GetInstance() new instance will be created as you wanted

Upvotes: 2

aevitas
aevitas

Reputation: 3833

Simple answer is: you shouldn't. Jon Skeet's description of the Singleton pattern is quite apt:

Essentially, a singleton is a class which only allows a single instance of itself to be created, and usually gives simple access to that instance.

A Form is possibly a poor candidate for a singleton instance - its state may change and you may need to show the form more than once. From my personal experience, the best candidates for singleton instances are classes which could be static, but either inherit another class or have to implement one or more interfaces. A Form doesn't fit those criteria very well.

So in way, the instance is still "there", but "disposed" (?)

Yes, if you really wanted to you could catch the ObjectDisposedException in your GetInstance method and re-create the instance of the form. This isn't the way to do it and actually goes against the whole idea of a singleton. Think twice whether you really want to follow the pattern before implementing a hack like this.

Upvotes: 4

Anton Kedrov
Anton Kedrov

Reputation: 1767

You can achieve it by canceling FormClosing event and hiding the form.

CancelEventArgs.Cancel Property

    private void frmCellInfo_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;
        this.Hide();
    }

Upvotes: 4

Related Questions