tags:

views:

421

answers:

4

Once a window has been closed, it is possible, and it is recommended, to reuse that window's Form instance to show the same window again? Or is it required or recommended to always create a brand new instance of the class when you will be showing a window.

What this really boils down to is whether it is a good idea to ever call Show() or ShowDialog() more than once on the same object, as long as the window is closed in between.

If this is not recommended, an explanation of the underlying reasons would also be appreciated.

+7  A: 

No, and no.

A call to Close ends up calling Dispose, and the object is considered disposed.

There is no problem in hiding the form and then showing it again, but closing it is a definite no-no, since the state is undefined after it is disposed (well, the state is disposed, but using it is the same as using something that is undefined).

casperOne
A: 

Yes you can, either you use singleton pattern, or put the form variable at class level:

class Form1
{
    Form2 _form2;

    void button1_Click()
    {
        _form2 = _form2 ?? new Form2();     
        _form2.Show();
    }
}


public Form2 
{
    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.UserClosing)
        {
            e.Cancel = true;
            this.Visible = false;
        }
    }
}

One reasonable use for example is if you implement your own FileOpen dialog box, you want its second invocation to remember where directory it was previously. Or notes-like window in your app, you need to retain the previous content even on succeeding invocations.

Michael Buen
Thanks, but the question is specifically about reusing the same object, without instantiating a new one.
Chris Ammerman
Yeah it doesn't instantiate a new one. Ok, instead of using ?? operator, convert to this: if (_form2 == null) _form2 = new Form2(); _form2.Show();
Michael Buen
Ah you're right, sorry I misread the code.
Chris Ammerman
Unfortunately, that doesn't work either. You have to set _form2 back to null when the FormClosing event on Form2 is fired.
casperOne
Why have to set to null? What's the purpose? I modify the code to facilitate (through CloseReason) closing/disposing of the form instance when other than user close the form. What doesn't work?
Michael Buen
+2  A: 

In my opinion this idea violates three principles: (1) avoid premature optimization, (2) the principle of least surprise, and (3) too tightly coupling data with user interface.

It seems that you're optimizing for time, but how much time? If displaying the form in question is very time- or resource-intensive, then, yes, it's probably not a bad thing to do what you suggest. But generally speaking, the pattern of creating a window and destroying it when the user interface no longer requires it to be visible is a time-tested practice. Furthermore, when a window is not visible, it's still taking up memory. And if that window relies on things like file handles or database connections, that's a potential source of bugs.

The principle of least surprise means to do things in expected ways for all users of the system, including end-users, maintainers, and developers. The pattern you're describing is unusual, and therefore might cause more problems than it's worth.

Another reason to avoid this practice is that it violates the spirit of the widely-used Model-View-Controller design pattern, which separates the object itself from the task of displaying or modifying the object. There are very good reasons to use this design pattern, and even if you don't, the philosophy behind it is a good one. An object's existence is usually not dependent on some user interface object, and therefore should exist separately from the user interface. For instance, a Customer object exists whether or not a window is being displayed that pertains to that Customer. Coupling data too tightly to user interface objects often leads to brittle, hard-to-change code.

If you do decide to implement this, I'd advise against creating too many of these hide-able windows and try to keep them to a minimum, in which case Michael Buen's code seems to be an elegant solution to the problem.

Jim Raden
I am using an MVP / humble dialog architecture, and the place where this question is relevant is in a class for obtaining service-specific settings dialogs. I was trying to decide whether to implement as a factory or registry. You and casperOne have convinced me factory is the only option.
Chris Ammerman
+1  A: 

When you are dealing with windows forms, ALWAYS create new instances. It is extremely easy to pack a lot of hidden state into a form and create an unforseen user experience all of a sudden on the 2nd, 3rd, or Nth invocation. In my experience, this effect increases dramatically as more controls and presentation code are added to the form.

Combine form instance reuse with anything short of nazi-level MVC seperation and you are asking for a major WTF moment, usually during functional testing.

Robert Venables