6

I was wondering if I am doing correctly.

I instantiate a Form (let's call this Form_B) within my class (also a form) and handle Form_B's Load event. Within this event I do some initialization.

Form_B can be displayed by the user multiple times, and I call ShowDialog on my instance variable.

The problem is that the Load is called each time I show the form. I tried debugging and also tried with Show() instead of ShowDialog(). Show() fails as I closed the window but ShowDialog() does not fail, but calls Load every time it is displayed.

Is it incorrect to continue using the instance once the form is closed?

Thanks, Stefan

Roy Lee
  • 10,572
  • 13
  • 60
  • 84
Vincent
  • 1,119
  • 11
  • 25

4 Answers4

13

Using the Load event to initialize a form is an anachronism from the VB6 days. It was really important back then, that unfortunately carried over in the design of the Winforms designer. It made Load the default event for a form.

That is however not the .NET way, you initialize a class object with the constructor. The only time you need to override OnLoad() (another .NET way, events are for code in other classes) is when you care about the size and position of the form. It won't be the design Size and Location when the user changed the Windows theme or runs the video adapter at a higher DPI setting. So you might want to use OnLoad to move the window or rearrange the controls. Not actually a very common thing to do.

So, fix your problem first by using the constructor instead. If you still need OnLoad then just use a bool flag that keeps track of whether or not it already ran.

    private bool initialized = false;

    protected override void OnLoad(EventArgs e) {
        if (!initialized) {
            initialized = true;
            // etc...
        }
        base.OnLoad(e);
    }

And yes, this only works if you use ShowDialog(). A form that's displayed with Show() automatically disposes itself when it is closed. That doesn't happen with ShowDialog() to avoid problems retrieving the dialog results. Re-creating the dialog instance is the better way, unless you really care about keeping the last entered values. That's however a really expensive way to do so, form objects take a lot of .NET and Windows resources.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Your advice is sound. I've gotten into a habit of trying to keep my constructors as small as possible - and possibly unconsciously avoiding exceptions being thrown inside a constructor. It's no excuse ofcourse, and handling exceptions should be done no matter where they are thrown. Thanks! – Vincent Mar 16 '11 at 08:24
3

That is the correct behaviour of the Load event, each time it is loaded it is called. If you want to reuse the form and avoid the the Load event, rather than close the form you should hide it and use the show method to bring it out when needed.

Robert MacLean
  • 38,975
  • 25
  • 98
  • 152
  • +1, @Vincent, to hide the control just use the Control.Hide method: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.hide.aspx – Adrian Fâciu Mar 15 '11 at 16:05
  • It's just that the http://msdn.microsoft.com/en-us/library/system.windows.forms.form.load.aspx documentation clearly states that it occurs when the form is displayed for the first time. I was beginning to think that perhaps ShowDialog was an exception to that event. – Vincent Mar 16 '11 at 08:17
2

The load event is called once all the components of the form are loaded. If you redisplay the form, its components load again and therefore the Load event is triggered once more.

You could trigger a custom event that would only be triggered in your form's constructor if that's what you're looking for but I think it's bad practice to use a form after it's been closed.

anthonyvd
  • 7,329
  • 4
  • 30
  • 51
  • 1
    Instead of a custom event why not just add your own initialization into the forms constructor? – HadleyHope Mar 15 '11 at 16:01
  • @HadleyHope Because it doesn't mean the initialization is acting upon members of that form. Suppose he waits for the form to load before doing something in his main class, then he needs to be outside the loaded form. – anthonyvd Mar 15 '11 at 17:17
  • Good point! raising that event within the "initialized" logic by @Hans Passant sounds correct. – Vincent Mar 16 '11 at 08:27
  • Also, in the case of inheritance and virtual members one must be careful not to call these within the constructor of the base class, so the (!initialized) logic is good! – Vincent Mar 16 '11 at 08:37
0

I'm having the same problem. After searching awhile, I think the "ShowDialog" is an exception.

Since it's 2018 right now, MS has opened .Net. I've checked the source and found this.

this.CalledOnLoad = false;
this.CalledMakeVisible = false;

in the ShowDialog() function.

https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Form.cs,ab288b84e00f8282

haiduong87
  • 316
  • 3
  • 14