Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1003
  • Last Modified:

What's the relation between Form.Load, Form.OnLoad, Form1_Load? Also OnShown?

Q1. How does a call to the Form.Load event end up being a call to the Form1_Load method? (OK I answer this myself below, so my next question is:)

Q2. What's the relation between the Form.Load event and the Form.OnLoad method?

Q3. How is the form's OnShown method called (who calls it)?


Let's see if I can trace this (I removed all 'using' statements to help clarify this for me):
namespace TestForm
{
  static class Program
  {
    [System.STAThread]
    static void Main()
    {
      System.Windows.Forms.Application.EnableVisualStyles();
      System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
      System.Windows.Forms.Application.Run(new Form1());
    }
  }
  public partial class Form1 : System.Windows.Forms.Form
  {
    public Form1()  //CONSTRUCTOR
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, System.EventArgs e)
    {
      //code...
    }
     protected override void OnShown(EventArgs e)
     {
       //code...
     }
  }
}

Open in new window


We start with
Application.Run(new Form1());

Open in new window

which creates an instance of class Form1 called I don't know, it's not assigned a name, it's just swallowed by Application.Run

So that instantiates an instance of System.Windows.Forms.Form named Form1

The code
public partial class Form1 : System.Windows.Forms.Form

Open in new window

somehow defines code at compile time for a class that doesn't exist until run time.

The CONSTRUCTOR for the newly instantiated class Form1 (which is an instance of the class System.Windows.Forms.Form) gets run which calls
InitializeComponent();

Open in new window


The InitializeComponent() code for Form1 is generated by Visual Studio in the Form1.Deisgner.cs file:
    private void InitializeComponent()
    {
      this.SuspendLayout();
      // 
      // Form1
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(284, 264);
      this.Name = "Form1";
      this.Text = "Form1";
      this.Load += new System.EventHandler(this.Form1_Load);
      this.ResumeLayout(false);
    }

Open in new window

And that's where Form1_Load comes from.

So I'm just left with questions Q2 and Q3 above.
0
deleyd
Asked:
deleyd
  • 4
  • 3
4 Solutions
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Hello:
A Q2: Form.OnLoad call the Load event if it have a event handler instance.
A @3: When the form is Show (Im not sure if it is called more that one time)
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
I did some reflection on System.Windows.Form class OnLoad method, this is the code:
protected virtual void OnLoad(EventArgs e)
{
    Application.OpenFormsInternalAdd(this);
    if (Application.UseWaitCursor)
    {
        base.UseWaitCursor = true;
    }
    if ((this.formState[FormStateAutoScaling] == 1) && !base.DesignMode)
    {
        this.formState[FormStateAutoScaling] = 0;
        this.ApplyAutoScaling();
    }
    if (base.GetState(0x20))
    {
        switch (((FormStartPosition) this.formState[FormStateStartPos]))
        {
            case FormStartPosition.CenterParent:
                this.CenterToParent();
                break;

            case FormStartPosition.CenterScreen:
                this.CenterToScreen();
                break;
        }
    }
    EventHandler handler = (EventHandler) base.Events[EVENT_LOAD];
    if (handler != null)
    {
        string text = this.Text;
        handler(this, e);
        foreach (Control control in base.Controls)
        {
            control.Invalidate();
        }
    }
    if (base.IsHandleCreated)
    {
        base.BeginInvoke(new MethodInvoker(this.CallShownEvent));
    }
}

Open in new window


As you can see, the OnShow method is called from this line:
base.BeginInvoke(new MethodInvoker(this.CallShownEvent));

Open in new window


private void CallShownEvent()
{
    this.OnShown(EventArgs.Empty);
}

Open in new window


This is the Load event handler code:
public event EventHandler Load
{
    add
    {
        base.Events.AddHandler(EVENT_LOAD, value);
    }
    remove
    {
        base.Events.RemoveHandler(EVENT_LOAD, value);
    }
}

Open in new window

You can see by your self by using .NET Reflector: http://www.reflector.net/
0
 
Todd GerbertIT ConsultantCommented:
Keep in mind that your Form inherits from System.Windows.Forms.Form - so all the code that makes up your Form object is much more than what you see in your project, there's quite a bit of code defined in the Framework's System.Windows.Forms.Form that you're inheriting from.

In your example Form_Load is a method in your object that subscribes to the Form's load event; the InitializeComponent() method is called in the constructor of your object, and in InitializeComponent() somewhere you should find a line similar to "this.Load += new EventHandler(Form_Load)".

OnLoad is a method in System.Windows.Forms.Form that is responsible for raising the Load event. You can override it to alter it's behavior.

OnShown is much like OnLoad, a method (defined in System.Windows.Forms.Form) that is responsible for raising the Shown event.  I would guess that Form.Show() calls OnShown.


>> somehow defines code at compile time for a class that doesn't exist until run time
The statement public partial class Form1 : System.Windows.Forms.Form simply declares a class named Form1 that inherits from System.Windows.Forms.Form, the "partial" keyword simply indicates that the class definition spans multiple .cs files (typically Form1.cs and Form1.Designer.cs).
0
Get your Conversational Ransomware Defense e‑book

This e-book gives you an insight into the ransomware threat and reviews the fundamentals of top-notch ransomware preparedness and recovery. To help you protect yourself and your organization. The initial infection may be inevitable, so the best protection is to be fully prepared.

 
Todd GerbertIT ConsultantCommented:
Maybe it would make more sense to look at a couple of simple objects in a console project.  In this example MyObject is analagous to your Form1, and MyBaseObject is analagous to your System.Windows.Forms.Form (in this example we see the code for the base object we've inherited from, but in the case of a Windows form you don't see the source code because it's already been compiled into System.Windows.Forms.dll).

Note that obj_Shown is never fired, because we overrode the OnShown method and didn't call the base's implementation.

using System;

class Program
{
	static void Main(string[] args)
	{
		// Create a couple object's
		MyObject obj1 = new MyObject();
		MyOtherObj obj2 = new MyOtherObj();

		// Listen to Load event
		obj1.Load += new EventHandler(obj1_Load);
		obj2.Load += new EventHandler(obj2_Load);

		// Listen to Shown event
		obj1.Shown += new EventHandler(obj1_Shown);
		obj2.Shown += new EventHandler(obj2_Shown);

		// Call the methods
		obj1.LoadObject();
		obj2.LoadObject();
		obj1.Show();
		obj2.Show();

		Console.Write("Press any key to exit...");
		Console.ReadKey();
	}

	static void obj2_Shown(object sender, EventArgs e)
	{
		Console.WriteLine("From Main(): obj2's Shown event handled.");
	}

	static void obj2_Load(object sender, EventArgs e)
	{
		Console.WriteLine("Form Main(): obj2's Load event handled.");
	}

	static void obj1_Shown(object sender, EventArgs e)
	{
		Console.WriteLine("From Main(): obj1's Shown event handled.");
	}

	static void obj1_Load(object sender, EventArgs e)
	{
		Console.WriteLine("From Main(): obj1's Load event handled.");
	}
}

public class MyOtherObj : MyBaseObject
{
	// This is like a Form without any customization
}

public class MyObject : MyBaseObject
{
	// Private InitializeComponent method
	private void InitializeComponent()
	{
		// Subscribe/listen to the "Load" event
		this.Load += new EventHandler(MyObject_Load);
	}

	// public constructor
	public MyObject()
	{
		InitializeComponent();
	}

	// The Load event handler
	private void MyObject_Load(object sender, EventArgs e)
	{
		Console.WriteLine("MyObject's Load event fired.");
	}

	// Override the OnShow method
	protected override void OnShown(EventArgs e)
	{
		// We are re-defining how OnShown runs
		// if we wanted to do whatever is done
		// in MyBaseObject.OnShown then we could 
		// call base.OnShown(e)
		// Since MyBaseObject.OnShown() is what
		// raises the Shown event, if we DON'T 
		// call that method then that event won't 
		// be raised
		Console.WriteLine("The object's Shown event has been preempted.");
	}
}

public class MyBaseObject
{
	// Declare events
	public event EventHandler Load;
	public event EventHandler Shown;

	// The On... methods are used to raise the events
	protected virtual void OnLoad(EventArgs e)
	{
		// if something's been assigned to the Load method,
		// i.e. at least one thing has subscribed to the Load event,
		// then execute all the methods that have been assigned
		// to this event - all the event handlers
		if (Load != null)
			Load(this, e);
	}

	protected virtual void OnShown(EventArgs e)
	{
		if (Shown != null)
			Shown(this, e);
	}

	// The "LoadObject" method
	public void LoadObject()
	{
		
		// Raise the "Load" event
		EventArgs e = new EventArgs();
		OnLoad(e);

		Console.WriteLine("This object has been loaded.");
	}

	// the "Show" method
	public void Show()
	{
		// Note that you don't necessarily have to assign an object to
		// a variable, it's perfectly valid to just pass "new Whatever()" 
		// as a method parameter - in reality it is being assigned to
		// a variable, in this case we're just specifying "new EventArgs()"
		// here, but in the OnLoad method that object ends up getting
		// assigned to the "e" variable. This is basically equivelant
		// to the method used in the LoadObject() method above

		// Raise the "Shown" event
		OnShown(new EventArgs());

		Console.WriteLine("This objects Show() method has executed.");
	}

}

Open in new window

0
 
Todd GerbertIT ConsultantCommented:
>> Note that obj_Shown is never fired, because we overrode the OnShown method and didn't call the base's implementation.

Correction ... obj1_Shown is never fired because MyObject overrides MyBaseObject's OnShown method.
0
 
John ClaesCommented:
After all this explaining it might also help you to read page.

see for the Page Life Cycle
http://msdn.microsoft.com/en-us/library/ms178472.aspx

0
 
Todd GerbertIT ConsultantCommented:
@poor_beggar

That link's for an ASP.Net page cycle, it doesn't really apply as the question pertains more to Windows Forms (and some of the more fundamental concepts of Object Oriented programming).
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Hello again, this is a MSDN article that talks about this, I think that is very good:
Order of Events in Windows Forms
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now