Recipe 18.8 Creating and Using Page Templates

     

18.8.1 Problem

Your application uses a common page format for most of its pages, and you want to reuse and simplify the maintenance of the shared HTML.

18.8.2 Solution

Review the HTML to determine what is common on all of your pages, and then create a user control for each of the common sections. The HTML page used as the basis for our example is shown in Example 18-21. Our user control for the top of the page is shown in Example 18-22 through Example 18-24 and for the bottom of the page in Examples Example 18-25 through Example 18-27.

Next, create a base page class that inherits from System.Web.UI.Page and loads the user controls you created at runtime. This base page class, along with the user controls containing the HTML for your pages, constitutes a "reusable HTML page template." Example 18-28 and Example 18-29 show the VB and C# versions of our base page class that demonstrate this solution.

You can then create the pages for your application by inheriting from the base class you have created instead of System.Web.UI.Page and add only the HTML that is unique to each page. Example 18-30 through Example 18-32 show the .aspx file and VB and C# code-behind file for an application that demonstrate the use of the base page class.

18.8.3 Discussion

Most applications use a common HTML design for the majority of their pages, and developers often find themselves cutting and pasting the common HTML in order to repeat the design on each page. Because of the replication, maintenance of the HTML is time consuming, expensive, and prone to mistakes. What is needed is the ability to code the HTML in one place and reuse it many times. This recipe describes how to implement a common design by reusing HTML.

The first step to creating reusable HTML is to analyze the HTML of your application pages to determine what elements are common across all of them. In our example that illustrates this solution, the two sections highlighted in Example 18-21 have been identified as being common across all pages. Figure 18-7 shows the output of the page in our example.

Figure 18-7. Page template example output
figs/ancb_1807.gif

For each common section, you need to create a user control. In our example, the first common section is placed in the CH18PageTopVB (VB) or CH18PageTopCS (C#) user control and the second common section is placed in the CH18PageBottomVB (VB) or CH18PageBottomCS (C#) user control, as shown in Example 18-22 and Example 18-25. The title element and the table cell used to place a label at the top of a page in the CH18PageTopxx user control have been modified from the original HTML to provide the ability to change the values of the title and page heading in the code-behind.

It may look a little odd to have HTML fragments in the user controls, but it is important to remember that the browser will only see the rendered page, which includes the HTML for each of the user controls, resulting in proper, well- formed HTML.


To provide the ability to change the values in the pages that use our example template, we have added the pageTitle and pageHeading properties to the code-behind of the CH18PageTopxx user control.

Our CH18PageBottomxx user control does not require any variation in the pages using the template; therefore, the code-behind for the user control does not require any additional code.

After creating the user controls containing the HTML to be reused, a new class must be created that will be used as the base class for all pages in your application. This class must inherit from the System.Web.UI.Page class to provide the base functionality needed for a page.

To provide the ability to change the properties in the pages that use our example template, the base page class must contain a property for each of the properties in the user controls. In our example, because a pageTitle and a pageHeading property were provided in the CH18PageTopxx user control, they must be added to the base page class.

The check at the beginning of each of the properties is necessary to avoid an error message indicating an object reference is not set to an instance of an object when using Visual Studio .NET. The error is caused by the designer accessing the properties for display purposes, but the user controls are not created in the designer, resulting in mPageTop and mPageHeading being null.


The OnInit method in our example must be overridden from the Page class to load the CH18PageTopVB (or CH18PageTopCS ) and CH18PageBottomVB (or CH18PageBottomCS ) user controls when the CH18BaseClassVB (or CH18BasePageCS ) object is created.

 
figs/vbicon.gif
 Protected Overrides Sub OnInit(ByVal e As System.EventArgs) 'load the user control containing the template for the top of the page 'and add it as the first control in the page  mPageTop = CType(LoadControl("CH18PageTopVB.ascx"), _   CH18PageTopVB)   MyClass.Controls.AddAt(0, mPageTop)  'take care of the base class initialization MyBase.OnInit(e) 'load the user control containing the template for the bottom of the page 'and add it at the end of the controls in the page  mPageBottom = CType(LoadControl("CH18PageBottomVB.ascx"), _   CH18PageBottomVB)   MyClass.Controls.Add(mPageBottom)  End Sub 'OnInit 
figs/csharpicon.gif
 protected override void OnInit(System.EventArgs e) { // take care of the base class initialization base.OnInit(e); // load the user control containing the template for the top of the page // and add it as the first control in the page  mPageTop = (CH18PageTopCS)(LoadControl("CH18PageTopCS.ascx"));   base.Controls.AddAt(0, mPageTop);  // load the user control containing the template for the bottom of the page // and add it at the end of the controls in the page  mPageBottom = (CH18PageBottomCS)(LoadControl("CH18PageBottomCS.ascx"));   base.Controls.Add(mPageBottom);  } // OnInit 

In our example, The CH18PageTopxx user control must be the first control on the page because it contains the HTML for the top of the page. In addition, the CH18PageBottomxx user control must be the last control on the form because it contains the HTML for the bottom of the page. Placing these controls at any other position in the controls collection will result in invalid HTML being rendered.


To use the page template, you need to create a web form as you normally would, but with two changes. First, the .aspx file should only include the HTML that is unique to the page being implemented, as shown in Example 18-30. In our example, the unique HTML is a simple table to provide the ability to format the content for the page.

The second modification is to change the inherited class for the code-behind class. This should be changed from the normal System.Web.UI.Page to the base class you created. In our example, the code-behind class inherits from CH18BasePageVB (or CH18BasePageCS for C#), which will result in the common HTML being output for the page.

In our example, two properties were included in the base page class to demonstrate how to reuse the HTML yet provide the ability to customize the output for each page. The properties must be set in the PageLoad method, as shown here:

 
figs/vbicon.gif
 Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If (Not Page.IsPostBack) Then 'set the page title  pageTitle = "Using the page template"  'set the page heading  pageHeading = "Simple Example Of Using A Page Template"  ... End If 'If (Not Page.IsPostBack) End Sub 'Page_Load 
figs/csharpicon.gif
 private void Page_Load(object sender, System.EventArgs e) { if (!Page.IsPostBack) { // set the page title  pageTitle = "Using the page template";  // set the page heading  pageHeading = "Simple Example Of Using A Page Template";  ... } // if (!Page.IsPostBack) 

Our example uses fairly simple HTML to demonstrate the implementation of a reusable HTML page template, but the technique is not limited to simple implementations . In fact, the more complicated the HTML, the more important it is to apply reuse to reduce the maintenance cost of the presentation portion of your application.

18.8.4 See Also

Chapter 4 for user controls

Example 18-21. Original HTML page
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">   <html>   <head>   <title>Original HTML Template</title>   <link rel="stylesheet" href="css/ASPNetCookbook.css">   </head>   <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">   <table width="100%" cellpadding ="0" cellspacing="0" border="0">   <tr>   <td align="center">   <img src="images/ASPCookbookHeading_blue.gif">   </td>   </tr>   <tr>   <td bgcolor ="#6B0808"><img src="images/spacer.gif" height="6"></td>   </tr>   </table>   <table width="90%" align="center" border="0">   <tr>   <td><img src="images/spacer.gif" height="10" border="0"></td>   </tr>   <tr>   <td align="center" class="PageHeading">   <!-- Put page heading here -->   </td>   </tr>   <tr>   <td><img src="images/spacer.gif" height="10" border="0"></td>   </tr>   <tr>   <td align="center">  <form method="post"> <!-- Put page content here --> </form>  </td>   </tr>   </table>   </body>   </html>  

Example 18-22. User control for top of page (.ascx)
 <%@ Control Language="vb" AutoEventWireup="false" Codebehind="CH18PageTopVB.ascx.vb" Inherits="ASPNetCookbook.VBExamples.CH18PageTopVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head>  <title id="mPageTitle" runat ="server"></title>  <link rel="stylesheet" href="css/ASPNetCookbook.css"> </head> <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td align="center"> <img src="images/ASPNETCookbookHeading_blue.gif"> </td> </tr> <tr> <td class="dividerLine"> <img src="images/spacer.gif" height="6" border="0"></td> </tr> </table> <table width="100%" align="center" border="0"> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr>  <td id="mPageHeading" runat="server"   align="center" class="PageHeading">  </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center"> 

Example 18-23. User control for top of page code-behind (.vb)
 Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name : CH18PageTopVB.ascx.vb ' ' Description: This class provides the code-behind for CH18PageTopVB.ascx ' '***************************************************************************** Namespace ASPNetCookbook.VBExamples Public Class CH18PageTopVB Inherits System.Web.UI.UserControl 'controls in the user control  Protected mPageTitle As System.Web.UI.HtmlControls.HtmlGenericControl   Protected mPageHeading As System.Web.UI.HtmlControls.HtmlTableCell  '************************************************************************* ' ' ROUTINE: pageTitle ' ' DESCRIPTION: This routine provides the ability to get/set the ' pageTitle property '-------------------------------------------------------------------------  Public Property pageTitle( ) As String   Get   Return (mPageTitle.InnerText)   End Get   Set(ByVal Value As String)   mPageTitle.InnerText = Value   End Set   End Property 'pageTitle  '************************************************************************* ' ' ROUTINE: pageHeading ' ' DESCRIPTION: This routine provides the ability to get/set the ' pageHeading property '-------------------------------------------------------------------------  Public Property pageHeading( ) As String   Get   Return (mPageHeading.InnerText)   End Get   Set(ByVal Value As String)   mPageHeading.InnerText = Value   End Set   End Property 'pageHeading  '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls ' on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'Put user code to initialize the page here End Sub 'Page_Load End Class 'CH18PageTopVB End Namespace 

Example 18-24. User control for top of page code-behind (.cs)
 //---------------------------------------------------------------------------- // // Module Name: CH18PageTopCS.ascx.cs // // Description: This module provides the code behind for CH18PageTopCS.ascx // //**************************************************************************** namespace ASPNetCookbook.CSExamples { using System; public abstract class CH18PageTopCS : System.Web.UI.UserControl { // controls in the user control  protected System.Web.UI.HtmlControls.HtmlGenericControl mPageTitle;   protected System.Web.UI.HtmlControls.HtmlTableCell mPageHeading;  //************************************************************************ // // ROUTINE: pageTitle // // DESCRIPTION: This routine provides the ability to get/set the // pageTitle property // //------------------------------------------------------------------------  public String pageTitle   {   get   {   return(mPageTitle.InnerText);   }   set   {   mPageTitle.InnerText = value;   }   } // pageTitle  //************************************************************************ // // ROUTINE: pageHeading // // DESCRIPTION: This routine provides the ability to get/set the // pageHeading property // //------------------------------------------------------------------------  public String pageHeading   {   get   {   return(mPageHeading.InnerText);   }   set   {   mPageHeading.InnerText = value;   }   } // pageHeading  //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on page. // //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here } // Page_Load } // CH18PageTopCS } 

Example 18-25. User control for bottom of page (.ascx)
 <%@ Control Language="vb" AutoEventWireup="false" Codebehind="CH18PageBottomVB.ascx.vb" Inherits="ASPNetCookbook.VBExamples.CH18PageBottomVB" %> </td> </tr> </table> </form> </body> </html> 

Example 18-26. User control for bottom of page code-behind (.vb)
 Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH18PageBottomVB.ascx.vb ' ' Description: This class provides the code-behind for CH18PageBottomVB.ascx ' '***************************************************************************** Namespace ASPNetCookbook.VBExamples Public Class CH18PageBottomVB Inherits System.Web.UI.UserControl '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls ' on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'Put user code to initialize the page here End Sub 'Page_Load End Class 'CH18PageBottomVB End Namespace 

Example 18-27. User control for bottom of page code-behind (.cs)
 //---------------------------------------------------------------------------- // // Module Name: CH18PageBottomCS.ascx.cs // // Description: This module provides the code behind for // CH18PageBottomCS.ascx // //**************************************************************************** using System; namespace ASPNetCookbook.CSExamples { public abstract class CH18PageBottomCS : System.Web.UI.UserControl { //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here } // Page_Load } // CH18PageBottomCS } 

Example 18-28. Base page class (.vb)
 Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH18BasePageVB.vb ' ' Description: This class provides the class used as the base class from ' which all ASPX pages in the application are derived. It ' provides the basic template for all of the common user ' interface. ' '***************************************************************************** Imports Microsoft.VisualBasic Namespace ASPNetCookbook.VBExamples Public Class CH18BasePageVB Inherits System.Web.UI.Page  'the following variables are used for references to the user controls   'that contain the top and bottom sections of the page template   Private mPageTop As CH18PageTopVB   Private mPageBottom As CH18PageBottomVB  '************************************************************************* ' ' ROUTINE: pageTitle ' ' DESCRIPTION: This routine provides the ability to get/set the ' pageTitle property '-------------------------------------------------------------------------  Public Property pageTitle( ) As String   Get   Dim title As String = String.Empty   If (Not IsNothing(mPageTop)) Then   title = mPageTop.pageTitle   End If   Return (title)   End Get   Set(ByVal Value As String)   If (Not IsNothing(mPageTop)) Then   mPageTop.pageTitle = Value   End If   End Set   End Property 'pageTitle  '************************************************************************* ' ' ROUTINE: pageHeading ' ' DESCRIPTION: This routine provides the ability to get/set the ' pageHeading property '-------------------------------------------------------------------------  Public Property pageHeading( ) As String   Get   Dim title As String = String.Empty   If (Not IsNothing(mPageTop)) Then   title = mPageTop.pageHeading   End If   Return (title)   End Get   Set(ByVal Value As String)   If (Not IsNothing(mPageTop)) Then   mPageTop.pageHeading = Value   End If   End Set   End Property 'pageHeading  '************************************************************************* ' ' ROUTINE: OnInit ' ' DESCRIPTION: This routine provides the event handler for the OnInit ' event. It is responsible for loading the user controls ' containing the page templates and adding them to the ' page controls collection. '-------------------------------------------------------------------------  Protected Overrides Sub OnInit(ByVal e As System.EventArgs)   'load the user control containing the template for the top of the page   'and add it as the first control in the page   mPageTop = CType(LoadControl("CH18PageTopVB.ascx"), _   CH18PageTopVB)   MyClass.Controls.AddAt(0, mPageTop)   'take care of the base class initialization   MyBase.OnInit(e)   'load the user control containing the template for the bottom of the page   'and add it at the end of the controls in the page   mPageBottom = CType(LoadControl("CH18PageBottomVB.ascx"), _   CH18PageBottomVB)   MyClass.Controls.Add(mPageBottom)   End Sub 'OnInit  End Class 'CH18BasePageVB End Namespace 

Example 18-29. Base page class (.cs)
 //---------------------------------------------------------------------------- // // Module Name: CH18BasePageCS.cs // // Description: This class provides the class used as the base class from // which all ASPX pages in the application are derived. It // provides the basic template for all of the common user // interface. // //**************************************************************************** using System; namespace ASPNetCookbook.CSExamples { public class CH18BasePageCS : System.Web.UI.Page {  // the following variables are used for references to the user controls   // that contain the top and bottom sections of the page template   private CH18PageTopCS mPageTop;   private CH18PageBottomCS mPageBottom;  //************************************************************************ // // ROUTINE: pageTitle // // DESCRIPTION: This routine provides the ability to get/set the // pageTitle property //------------------------------------------------------------------------  public String pageTitle   {   get   {   String title = String.Empty;   if (mPageTop != null)   {   title = mPageTop.pageTitle;   }   return(title);   }   set   {   if (mPageTop != null)   {   mPageTop.pageTitle = value;   }   }   } // pageTitle  //************************************************************************ // // ROUTINE: pageHeading // // DESCRIPTION: This routine provides the ability to get/set the // pageHeading property //------------------------------------------------------------------------  public String pageHeading   {   get   {   String title = String.Empty;   if (mPageTop != null)   {   title = mPageTop.pageHeading;   }   return(title);   }   set   {   if (mPageTop != null)   {   mPageTop.pageHeading = value;   }   }   } // pageHeading  // *********************************************************************** // // ROUTINE: OnInit // // DESCRIPTION: This routine provides the event handler for the OnInit // event. It is responsible for loading the user controls // containing the page templates and adding them to the // page controls collection. //---------------------------------------------------------------------------  protected override void OnInit(System.EventArgs e)   {   // take care of the base class initialization   base.OnInit(e);   // load the user control containing the template for the top of the page   // and add it as the first control in the page   mPageTop = (CH18PageTopCS)(LoadControl("CH18PageTopCS.ascx"));   base.Controls.AddAt(0, mPageTop);   // load the user control containing the template for the bottom of the page   // and add it at the end of the controls in the page   mPageBottom = (CH18PageBottomCS)(LoadControl("CH18PageBottomCS.ascx"));   base.Controls.Add(mPageBottom);   } // OnInit  } // CH18BasePageCS } 

Example 18-30. Using the base page class (.aspx)
 <%@ Page Language="vb" AutoEventWireup="false" Codebehind="CH18UsingThePageTemplateVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH18UsingThePageTemplateVB"%> <form method="post" id="frmUsingPageTemplate" runat="server"> <!-- Put page content here --> <table width="80%" border="0" align="center"> <tr> <td> <asp:Xml ID="xmlTransform" Runat="server"/> </td> </tr> </table> </form> 

Example 18-31. Using the base page class code-behind (.vb)
 Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH18UsingThePageTemplateVB.aspx.vb ' ' Description: This class provides the code-behind for ' CH18UsingThePageTemplateVB.aspx ' '***************************************************************************** Imports System Namespace ASPNetCookbook.VBExamples Public Class  CH18UsingThePageTemplateVB  Inherits CH18BasePageVB 'controls on the form Protected xmlTransform As System.Web.UI.WebControls.Xml '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls ' on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If (Not Page.IsPostBack) Then  'set the page title   pageTitle = "Using the page template"   'set the page heading   pageHeading = "Simple Example Of Using A Page Template"  'initialize controls on the specific page 'set the names of the XML and XSLT documents used in the 'transformation xmlTransform.DocumentSource = "xml/books.xml" xmlTransform.TransformSource = "xml/books.xslt" End If 'If (Not Page.IsPostBack) End Sub 'Page_Load End Class 'CH18UsingThePageTemplateVB End Namespace 

Example 18-32. Using the base page class code-behind (.cs)
 //---------------------------------------------------------------------------- // // Module Name: CH18UsingThePageTemplateCS.aspx.cs // // Description: This module provides the code behind for the // CH18UsingThePageTemplateCS.aspx page // //**************************************************************************** using System; namespace ASPNetCookbook.CSExamples { public class CH18UsingThePageTemplateCS :  CH18BasePageCS  { // controls on the form protected System.Web.UI.WebControls.Xml xmlTransform; //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { if (!Page.IsPostBack) {  // set the page title   pageTitle = "Using the page template";   // set the page heading   pageHeading = "Simple Example Of Using A Page Template";  // initialize controls on the specific page // set the names of the XML and XSLT documents used in the // transformation xmlTransform.DocumentSource = "xml//books.xml"; xmlTransform.TransformSource = "xml//books.xslt"; } // if (!Page.IsPostBack) } // Page_Load } // CH18UsingThePageTemplateCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2006
Pages: 179

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net