Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Creating Usable Page Templates in ASP.NET : Page 3

Overcome ASP.NET's lack of page templating using this robust and upgradeable templating approach.

Building the PageBody Server Control
The most important aspect of this model is exposing a server control to the calling page which controls the loading and customizing of the underlying page template. The purpose of doing this is to control the instantiation of all the page-specific content on the calling page, both static HTML as well as dynamic controls. By doing so, we can guarantee that all the server controls can participate in the intrinsic events, such as Init, Load, and LoadViewState. This would not be possible with the other ad hoc methods mentioned above.

Listing 5 shows the code for the PageBody server control. The control serves two major functions. First, by overriding the appropriate methods, it controls the instantiation of the child controls found on the page so that they are declared inside the placeholder of the page template. Second, it exposes public properties which are part of the customization process. In the case of the example above, the table cell containing the header requires a different CSS class attribute value when users are logged in or out. The HeaderCSSClass property holds the customizable data element:

Public Property HeaderCssClass() As String

To understand the code you need to visualize the timeline of execution. When the browser requests an .aspx page that consumes the template the ASP.NET engine must first parse the text for tag data. When it parses the tag for the PageBody control, it instantiates that class and then populates the values mapped to the properties, if any exist in the opening tag. As the parser continues to parse the inner text, it repeatedly calls the AddParsedSubObject() method, adding each inner child control to the _ControlList ArrayList. Later, the runtime calls the CreateChildControls() method. At that point, the PageBody control adds the controls in the ArrayList into the NamingPlaceHolder found inside the page template.

One can argue that it would be cleaner and simpler to eliminate the PageBody control from this architecture and declare the page template user control itself in the calling page. There are some problems with that approach. First, this creates an ambiguity between the child controls declared in the .ascx file and the child controls contained within the nested template calling tags. Actually what happens is the ASP.NET runtime places the child controls contained within its calling tags directly after the code in the .ascx file. It would be a mess to try to figure out where this partition occurs, and would eventually require hacks to make it work. The other major problem is one of flexibility—by using this server control as a bridge, you can not only customize the template, but you can take it a step further an allow the page to choose from one or more available page templates, if your application requires it.

As pointed out previously, because the CreateChildControls() method is implemented, the template and the page-level content are merged so that the page-level controls participate in the ASP.NET intrinsic events. If you load a user control programmatically from another user control or from the page, that user control does not participate in events which precede the point at which it was loaded. In other words, if you load a user control during the Page.Load event, the events which come before it are not raised within the user control, so handlers such as Page_Init do not get executed. For more information, visit the Control Execution Lifecycle page at MSDN.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date