Despite working with WebForms for years I still find myself getting confused about the event lifecycle from time to time. This isn't so much a problem that needs resolving, as hoping to get a better understanding of why things work the way they do.
Suppose you have a form:
Default.aspx:
<form>
<MyControls:UserControl1 runat="server">
</form>
UserControl1:ascx:
<MyControls:UserControl2 runat="server">
The OnInit
events occur in this order:
UserControl2_OnInit
UserControl1_OnInit
Default_OnInit
Isn't this just bass-ackwards? Shouldn't the Init code be run in the order that controls are created? Shouldn't a parent control be able to initialize properties of a child before its OnInit runs? That is, while you can initialize properties of subcontrols in markup, there's no direct way to have a parent control be able to dynamically set properties of the child control that will be available to its OnInit event.
What I've ended up doing is stuff like this:
override void UserControl2_OnInit()
{
NamingContainer.OnInit += new EvenHandler(UserControl1_ActualInit);
}
protected void UserControl2_ActualInit(..) {
// do actual init code here, which will occur before OnLoad but after it's parent
// OnInit
}
So it's not an insurmountable problem. I just don't understand why it's a problem in the first place.
I realize that perhaps you might want to be able to have all your child controls initialized in your OnInit code. So fine, you should be able to call base.OnInit first, instead of after, your own initialization code, which should cause all the child control OnInit events to get run. But the event lifecycle doesn't work that way. The Init events are not chained recursively, they seem to run independently the parent events, and the innermost one always gets run first. But seems life would be a lot easier if they were simply chained recursively so you could either call the base event (or not) before you do your thing in any given situation. Is there something I'm missing that makes this seemingly counterintuitive situation desirable or even necessary?
This document should be the main source of truth for your lifecycle questions.
Basically, OnInit fires after a control's internal initialization in finished. Since the page control is the first control initialized, and during it's internal initialization it initializes all sub-controls (perhaps in the order that the Designer.cs file gives), then it makes sense for the Page's OnInit event to be the last one called, since it's not finished initializing until all it's sub-controls are initialized and their OnInit events fired. Graphically, it looks like this:
So order of inits in this case is:
Load also work similarly. In general you should treat most of the events as though the control will go through it's internal process first (which includes calling the same event on all sub-controls), and then fire your custom event handling code afterwards.
Most examples you find use Page_Load specifically because that should be the last event called in that phase (and it's after post back data is loaded). It wouldn't work very well for Page_Load to be called first and risk having controls not in a fully loaded state for your custom event handling code.