Open New Window For Code Reference
The next crucial step is to override the
Page.Init method and call the custom initialization procedure,
LoadControls. This is where most of the work gets done, where the control tree is initialized for the page.
I've included a mythical "TopBar" control to illustrate that if you have any standard site navigation, images, etc., you should load them into web user controls (as you probably would even if you weren't using a templating scheme). These controls will be placed in the basic page layout for your site that you create in the
So, the first thing I do in the
LoadControls method is load up my
TopBar control. I then assign all of my
Id property (on the off chance you need to
Find them by their
Id at some point). Then comes the page layout. I've created a little helper method,
AddStaticText, that I use to add literal controls where static text is needed. (In case you don't know, each contiguous bit of HTML/Text that you put on an ASPX/ASCX page is parsed into a
LiteralControl, so we're just using the same method that ASP.NET does to add text like this to the control tree.)
You'll note that I'm using
LiteralControl controls for the <TITLE /> and stylesheet declarations that use the
StyleSheet properties for their values. This of course assumes that you'll be using a stylesheet file. If you are not, you can simply remove the code for the
StyleSheet property. The same goes for any of the other default controls on this template--there is no requirement to create all of the same place holders that I have--feel free to change them around all you like.
The next thing I do is add my "Head"
PlaceHolder to the control collection. This of course is there to make it easy to add client-side script functions in what I believe to be the proper place. If you wanted to go all out, you could go ahead and create a "Script"
PlaceHolder that writes out the <SCRIPT /> tags for you.
After opening the body, I go ahead and add my
TopBar control. If I had a more complex layout, such as a left and right bar containing ads, navigation, or what have you, I would likely build the layout here with a table that has the least amount of formatting and content possible here because modifying UI on user controls is easier than modifying UI in code.
Next, I add a "body" DIV with a specific
Id ("bodyDiv") so that I can give the "body" specific styles by creating a CSS Id declaration. You could do this with a CSS class as well, depending on preference. Then, to the
Body PlaceHolder, I add all of the parsed controls from the child ASPX. Again, this place holder is arbitrary; I simply used it to expose another place to add controls to programmatically if I, or any user of this template, so desire.
After this, I add the
Body PlaceHolder to the main form. This is a key step; in order for controls in the ASPX to participate in postback and raise corresponding events, they must be part of the server-side form. So you could have skipped adding the parsed controls to the
Body PlaceHolder and added them directly to the form, but as I said, I used the
Body PlaceHolder to enable consumers of the class to know exactly where the parsed controls are added in the control tree and to expose it for them to add more controls via code. The key thing to remember is that for a control to participate in postback and/or raise any of its server-side events, it MUST be part of the server-side form.
Key Note:This brings up an important consideration. Some of the other templating schemes I've seen do not create a server-side form for you. In cases where you're producing mostly static content that does not require server-side, object-oriented postback handling, having a server-side form is largely unnecessary; however, if most of your pages will need postback handling (such as in a web application in the strict sense) and given that ASP.NET limits you to one and only one server-side form, it makes sense to create that one server-side form in your base page class (your template class) so that you do not have to declare it on every page and so that all parts of your page template (such as your various navigation controls and the controls parsed from the ASPX) can participate in object-oriented postback event handling and view state.
Keep in mind that this is not the same thing as placing a server-side form in a user control. Microsoft rightly recommends against that because it limits postback participation to those server controls in your user control. In this template, however, all (or as many as you want) server controls will be added to the server-side form and can thus participate in postback.
Page.Controls collection (a vital but simple step), and I close the BODY and HTML tags for the page.