There's tons of info on the web about the ASP.NET life cycle, but i can't seem to figure out when to dynamically add controls to the page.
In general there are two situations; an aspx page with a masterpage, and one without. The book i'm currently reading (70-515 self prep) says to add controls to a page without a master page in the preinit eventhandler. To dynamically add controls to a contentpage, i should place that logic in the init eventhandler.
According to MSDN (http://msdn.microsoft.com/en-us/library/ms178472.aspx) I should create or recreate dynamic controls in the preinit eventhandler, and only read or initialize properties of controls in the init eventhandler (which makes most sense to me). Googling around I see lots of people using the init eventhandler to add controls.
So, i'm a little bit lost here - what is the correct way? And when using the preinit eventhandler, how could you add controls to your page when all controls are null? For instance, when you need to add a dynamically created textbox to a panel control?
Kind regards,
Unless you need to play around with setting control properties prior to tracking ViewState, I would personally go ahead and place my dynamic control addition logic in the OnInit event.
If you really want to dynamically add a control during the PreInit (when using master page) you can always do something like this:
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
TextBox textBox = new TextBox();
textBox.Text = "Dynamic TextBox";
textBox.Width = 100;
textBox.ReadOnly = false;
var master = this.Master;
plcHolder.Controls.Add(textBox);
textBox.ApplyStyleSheetSkin(this.Page);
}
accessing the "Master" property would instantiate the controls and it should work, but you get nested master pages scenarios (this.Master.Master ...), update panels and so on.
This might be relevant and helpful: http://weblogs.asp.net/ysolodkyy/archive/2007/10/09/master-page-and-preinit.aspx
Moreover, one reason I can think of (besides following the defined page lifecycle) MS recommends that we place all the logic for dynamic control creation in the Preinit event so we can take advantage of the theme service, which will apply all available skin properties automatically for us, before the Init event takes place.
Say your markup looks something like that:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Trace="true" Inherits="_Default" Theme="Test" %>
...
<form id="form1" runat="server">
<div>
<p>
<asp:TextBox ID="TextBox1" runat="server" TextMode="Password" Text="Control TextBox"></asp:TextBox>
</p>
<p>
<asp:PlaceHolder ID="plcHolder" runat="server"></asp:PlaceHolder>
</p>
</div>
</form>...
and you have a skin like this:
<asp:TextBox runat="server" BackColor="Yellow" Wrap="false" Text="Skin property!" > </asp:TextBox>
Just add this to your code behind:
private TextBox tb1;
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
tb1 = new TextBox();
tb1.Text = "PreInit Dynamic TextBox";
Trace.Write(String.Format("tb1 Wrap Property-> {0}",tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
Trace.Write("Add tb1 to the placeholder.");
plcHolder.Controls.Add(tb1);
Trace.Write(String.Format("tb1 Wrap Property-> {0}", tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
}
protected override void OnInit(EventArgs e)
{
Trace.Write(String.Format("tb1 Wrap Property-> {0}", tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
base.OnInit(e);
}
protected void Page_Load(object sender, EventArgs e)
{
Trace.Write(String.Format("tb1 Wrap Property-> {0}", tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
}
You will notice how before going into the Init event all skin properties are already applied to the dynamically created textbox :)