Providing Unique Control IDs
The final step is to create a naming placeholder. To do that, create a class that inherits from PlaceHolder and implements the INamingContainer interface. The following code a NamingPlaceHolder control class. The control extends the ASP.NET PlaceHolder control by guaranteeing that controls contained within have their own isolated namespace, eliminating duplicate IDs.
' This class extends the PlaceHolder class.
' This implementation gives all the child controls
' within a unique naming space, eliminating the possibility
' of a naming collision among one or more
' IDs between the pages and the page template.
Public Class NamingPlaceHolder
INamingContainer is a marker interface that, when implemented by a control, creates unique IDs for its child controls. For example, when a control that implements INamingContainer has an ID of ctrlMain
, its child controls will have IDs prefixed with this parent ID plus a colon, such as ctrlMain:TextBox1
. This naming scheme guards against potentially dangerous naming collisions; the ASP.NET runtime will throw an exception if a server control inside the page template has the same ID as a control on the calling page. With potentially large sites, this extra step avoids the tedious task of manually ensuring that the IDs of server controls on the pages do not conflict with any IDs in any of the page templates for the site.
Putting It Together
You can see how efficient and elegant this approach is. The following code shows the TypicalPage.aspx
page with page templating implemented. As you can see, the code for the page has been significantly reduced. The page can now use the PageBody server control instead of copying the same HTML code from page to page. Using the page template, designers can manage template layout and page-level content layout separately.
<title>My Site - Home</title>
<!-- page-specific content -->
The beauty of this architecture is that it you can extend it to allow more than one page template. Furthermore, you can encapsulate the PageBody and NamingPlaceHolder classes in its own implementation for reuse in other Web applications. Each application would then inherit from PageBody, adding the properties required by the Web designers to customize the template.