Chapter 5. Designing Websites with Master Pages

<feature><title>In this Chapter</title> <objective>

Creating Master Pages

</objective>
<objective>

Modifying Master Page Content

</objective>
<objective>

Dynamically Loading Master Pages

</objective>
<objective>

Summary

</objective>
</feature>

A Master Page enables you to share the same content among multiple content pages in a website. You can use a Master Page to create a common page layout. For example, if you want all the pages in your website to share a three-column layout, you can create the layout once in a Master Page and apply the layout to multiple content pages.

You also can use Master Pages to display common content in multiple pages. For example, if you want to display a standard header and footer in each page in your website, then you can create the standard header and footer in a Master Page.

By taking advantage of Master Pages, you can make your website easier to maintain, extend, and modify. If you need to add a new page to your website that looks just like the other pages in your website, then you simply need to apply the same Master Page to the new content page. If you decide to completely modify the design of your website, you do not need to change every content page. You can modify just a single Master Page to dramatically change the appearance of all the pages in your application.

In this chapter, you learn how to create Master Pages and apply Master Pages to content pages. It describes how you can apply a Master Page to an entire application by registering the Master Page in the web configuration file.

It also explores different methods of modifying content in a Master Page from individual content pages. For example, you learn how to change the title displayed by a Master Page for each content page.

Finally, you learn how to load Master Pages dynamically. Loading Master Pages dynamically is useful when you need to co-brand one website with another website, or when you want to enable individual website users to customize the appearance of your website.

Creating Master Pages

You create a Master Page by creating a file that ends with the .master extension. You can locate a Master Page file any place within an application. Furthermore, you can add multiple Master Pages to the same application.

For example, Listing 5.1 contains a simple Master Page.

Example 5.1. SimpleMaster.master

<%@ Master Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        html
        {
            background-color:silver;
            font:14px Arial,Sans-Serif;
        }
        .content
        {
            margin:auto;
            width:700px;
            background-color:white;
            border:Solid 1px black;
        }
        .leftColumn
        {
            float:left;
            padding:5px;
            width:200px;
            border-right:Solid 1px black;
            height:700px;

        }
        .rightColumn
        {
            float:left;
            padding:5px;
        }
        .clear
        {
            clear:both;
        }
    </style>
    <title>Simple Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <div class="content">
        <div class="leftColumn">

            <asp:contentplaceholder
                id="ContentPlaceHolder1"
                runat="server"/>

        </div>
        <div class="rightColumn">

            <asp:contentplaceholder
                id="ContentPlaceHolder2"
                runat="server"/>

        </div>
        <br class="clear" />
    </div>
    </form>
</body>
</html>

Notice that the Master Page in Listing 5.1 looks very much like a normal ASP.NET page. In fact, you can place almost all the same elements in a Master Page that you could place in an ASP.NET page, including HTML, server-side scripts, and ASP.NET controls.

Visual Web Developer Note

You create a Master Page in Visual Web Developer by selecting the Website menu option, Add New Item, and selecting the Master Page item.

There are two special things about the Master Page in Listing 5.1. First, notice that the file contains a <%@ Master %> directive instead of the normal <%@ Page %> directive. Second, notice that the Master Page includes two ContentPlaceHolder controls.

When the Master Page is merged with a particular content page, the content from the content page appears in the areas marked by ContentPlaceHolder controls. You can add as many ContentPlaceHolders to a Master Page as you need.

Warning

There are some things that you can’t do in a Master Page that you can do in a content page. For example, you cannot cache a Master Page with the OutputCache directive. You also cannot apply a theme to a Master Page.

The Master Page in Listing 5.1 creates a two-column page layout. Each ContentPlaceHolder control is contained in a separate <div> tag. Cascading Style Sheet rules are used to position the two <div> tags into a two-column page layout (see Figure 5.1).

Creating a two-column Master Page.

Figure 5.1. Creating a two-column Master Page.

Web Standards Note

The Master Page uses Cascading Style Sheets to create the page layout. You should strive to avoid using HTML tables for layout. HTML tables should be used only to display tabular information.

The content page in Listing 5.2 uses the Master Page that was just created.

Example 5.2. SimpleContent.aspx

<%@ Page Language="VB" MasterPageFile="~/SimpleMaster.master" %>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
</asp:Content>

<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
</asp:Content>

When you open the page in Listing 5.2 in a web browser, the contents of the page are merged with the Master Page.

Visual Web Developer Note

In Visual Web Developer, you create an ASP.NET page that is associated with a particular Master Page by selecting Website, Add New Item, and selecting Web Form. Next, check the check box labeled Select Master Page. When you click Add, a dialog box appears that enables you to select a Master Page.

The Master Page is associated with the content page through the MasterPageFile attribute included in the <%@ Page %> directive. This attribute contains the virtual path to a Master Page.

Notice that the content page does not contain any of the standard opening and closing XHTML tags. All these tags are contained in the Master Page. All the content contained in the content page must be added with Content controls.

You must place all the content contained in a content page within the Content controls. If you attempt to place any content outside these controls, you get an exception.

The Content control includes a ContentPlaceHolderID property. This property points to the ID of a ContentPlaceHolder control contained in the Master Page.

Within a Content control, you can place anything that you would normally add to an ASP.NET page, including XHTML tags and ASP.NET controls.

Creating Default Content

You don’t have to associate a Content control with every ContentPlaceHolder control contained in a Master Page. You can provide default content in a ContentPlaceHolder control, and the default content will appear unless it is overridden in a particular content page.

For example, the Master Page in Listing 5.3 includes an additional column, which displays a banner advertisement (see Figure 5.2). The banner advertisement is contained in a ContentPlaceHolder control named contentAd.

Displaying default content in a Master Page.

Figure 5.2. Displaying default content in a Master Page.

Example 5.3. DefaultMaster.master

<%@ Master Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        html
        {
            background-color:silver;
            font:14px Arial,Sans-Serif;
        }
        .content
        {
            margin:auto;
            width:700px;
            background-color:white;
            border:Solid 1px black;
        }
        .leftColumn
        {
            float:left;
            padding:5px;
            width:200px;
            border-right:Solid 1px black;
            height:700px;

        }
        .middleColumn
        {
            float:left;
            padding:5px;
        }
        .rightColumn
        {
            float:right;
            width:175px;
            height:300px;
            border-left:solid 1px black;
            border-bottom:solid 1px black;
            background-color:#eeeeee;
            text-align:center;
        }
        .ad
        {
            margin-top:20px;
        }
        .clear
        {
            clear:both;
        }
    </style>
    <title>Default Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <div class="content">
        <div class="leftColumn">

            <asp:contentplaceholder
                id="ContentPlaceHolder1"
                runat="server"/>

        </div>
        <div class="middleColumn">

            <asp:ContentPlaceholder
                id="ContentPlaceHolder2"
                runat="server" />

        </div>
        <div class="rightColumn">

            <asp:ContentPlaceHolder
                id="contentAd"
                Runat="server">
                <asp:Image
                    id="imgAd"
                    ImageUrl="~/BannerAd.gif"
                    CssClass="ad"
                    AlternateText="Advertisement for Superexpert ASP Workshops"
                    Runat="server" />
            </asp:ContentPlaceHolder>

        </div>
        <br class="clear" />
    </div>
    </form>
</body>
</html>

The content page in Listing 5.4 uses the Master Page in Listing 5.3. It does not include a Content control that corresponds to the contentAd control in the Master Page. When you open the page in a browser, the default banner advertisement is displayed.

Example 5.4. DefaultContent.aspx

<%@ Page Language="VB" MasterPageFile="~/DefaultMaster.master" %>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
</asp:Content>

<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
</asp:Content>

Of course, you do have the option of adding a Content control that overrides the default content contained in the contentAd control in the Master Page. For example, you might want to display different banner advertisements in different sections of your website.

Note

You can nest ContentPlaceHolder controls in a Master Page. If you do this, then you have the option of overriding greater or smaller areas of content in the Master Page.

Nesting Master Pages

When building a large website, you might need to create multiple levels of Master Pages. For example, you might want to create a single site-wide Master Page that applies to all the content pages in your website. In addition, you might need to create multiple section-wide Master Pages that apply to only the pages contained in a particular section.

Warning

You cannot work with nested Master Pages in Visual Web Developer while in Design view. If you need to nest Master Pages, then you need to stick to Source view.

You can nest Master Pages as many levels as you need. For example, Listing 5.5 contains a Master Page named Site.master, which displays a logo image and contains a single content area. It also contains site-wide navigation links.

Example 5.5. Site.master

<%@ Master Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        html
        {

            background-color:DarkGreen;
            font:14px Georgia,Serif;
        }
        .content
        {
            width:700px;
            margin:auto;
            border-style:solid;
            background-color:white;
            padding:10px;
        }
        .tabstrip
        {
            padding:3px;
            border-top:solid 1px black;
            border-bottom:solid 1px black;
        }
        .tabstrip a
        {
            font:14px Arial;
            color:DarkGreen;
            text-decoration:none;
        }
        .column
        {
            float:left;
            padding:10px;
            border-right:solid 1px black;
        }
        .rightColumn
        {
            float:left;
            padding:10px;
        }
        .clear
        {
            clear:both;
        }
    </style>
    <title>Site Master</title>
</head>
<body>
    <form id="form1" runat="server">

    <div class="content">
        <asp:Image
            id="imgLogo"
            ImageUrl="~/Images/SiteLogo.gif"
            AlternateText="Website Logo"
            Runat="server" />

        <div class="tabstrip">
        <asp:HyperLink
            id="lnkProducts"
            Text="Products"
            NavigateUrl="~/Products.aspx"
            Runat="server" />
        &nbsp;
        <asp:HyperLink
            id="lnkServices"
            Text="Services"
            NavigateUrl="~/Services.aspx"
            Runat="server" />
        </div>
        <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
        </asp:contentplaceholder>
        <br class="clear" />
        copyright &copy; 2007 by the Company
    </div>
    </form>
</body>
</html>

The Master Pages in Listing 5.6 and Listing 5.7 are nested Master Pages. Notice that both Master Pages include a MasterPageFile attribute that points to the Site.master Master Page.

Example 5.6. SectionProducts.master

<%@ Master Language="VB" MasterPageFile="~/Site.master" %>

<asp:Content
    id="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="server">
    <div class="column">
        <asp:ContentPlaceHolder
            id="ContentPlaceHolder1"
            Runat="server" />
    </div>
    <div class="column">
        <asp:ContentPlaceHolder
            id="ContentPlaceHolder2"
            Runat="server" />
    </div>
    <div class="rightColumn">
        <asp:ContentPlaceHolder
            id="ContentPlaceHolder3"
            Runat="server" />
    </div>
</asp:Content>

Example 5.7. SectionServices.master

<%@ Master Language="VB" MasterPageFile="~/Site.master" %>

<asp:Content
    id="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="server">
    <div class="column">
        <asp:ContentPlaceHolder
            id="ContentPlaceHolder1"
            Runat="server" />
    </div>
    <div class="rightColumn">
        <asp:ContentPlaceHolder
            id="ContentPlaceHolder2"
            Runat="server" />
    </div>
</asp:Content>

The Master Page in Listing 5.6 creates a three-column page layout, and the Master Page in Listing 5.7 creates a two-column page layout.

The Products.aspx page in Listing 5.8 uses the SectionProducts.master Master Page. When you request the Products.aspx page, the contents of Site.master, SectionProducts.master, and Products.aspx are combined to generate the rendered output (see Figure 5.3).

Nesting Master Pages to display the Products.aspx page.

Figure 5.3. Nesting Master Pages to display the Products.aspx page.

Example 5.8. Products.aspx

<%@ Page Language="VB" MasterPageFile="~/SectionProducts.master" %>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
</asp:Content>

<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
</asp:Content>

<asp:Content
    ID="Content3"
    ContentPlaceHolderID="ContentPlaceHolder3"
    Runat="Server">
    Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
    <br />Products, Products, Products
</asp:Content>

The Services.aspx page in Listing 5.9 uses the SectionService.master Master Page. When this page is opened in a browser, the contents of Site.master, SectionServices.master, and Services.aspx are combined to generate the rendered output (see Figure 5.4).

Example 5.9. Services.aspx

<%@ Page Language="VB" MasterPageFile="~/SectionServices.master"
    Title="Untitled Page" %>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Services, Services, Services
    <br />Services, Services, Services
    <br />Services, Services, Services
    <br />Services, Services, Services
    <br />Services, Services, Services
</asp:Content>
<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Services, Services, Services, Services, Services
    <br />Services, Services, Services, Services, Services
    <br />Services, Services, Services, Services, Services
    <br />Services, Services, Services, Services, Services
    <br />Services, Services, Services, Services, Services
</asp:Content>
Nesting Master Pages to display the Services.aspx pages.

Figure 5.4. Nesting Master Pages to display the Services.aspx pages.

Using Images and Hyperlinks in Master Pages

You must be careful when using relative URLs in a Master Page. For example, you must be careful when adding images and links to a Master Page. Relative URLs are interpreted in different ways, depending on whether they are used with HTML tags or ASP.NET controls.

If you use a relative URL with an ASP.NET control, then the URL is interpreted relative to the Master Page. For example, suppose that you add the following ASP.NET Image control to a Master Page:

<asp:Image ImageUrl="Picture.gif" Runat="Server" />

The ImageUrl property contains a relative URL. If the Master Page is located in a folder named MasterPages, then the URL is interpreted like this:

/MasterPages/Picture.gif

Even if a content page is located in a completely different folder, the ImageUrl is interpreted relative to the folder that contains the Master Page and not relative to the content page.

The situation is completely different in the case of HTML elements. If an HTML element such as an <img> or <a> tag includes a relative URL, the relative URL is interpreted relative to the content page. For example, suppose you add the following <img> tag to a Master Page:

<img src="Picture.gif" />

The src attribute contains a relative URL. This URL is interpreted relative to a particular content page. For example, if you request a content page located in a folder named ContentPages, the relative URL is interpreted like this:

/ContentPages/Picture.gif

Using relative URLs with HTML elements is especially tricky because the URL keeps changing with each content page. If you request content pages from different folders, the relative URL changes. There are three ways that you can solve this problem.

First, you can replace all the HTML elements that use relative URLs with ASP.NET controls. An ASP.NET control automatically reinterprets a relative URL as relative to the Master Page.

Note

Relative URLs used by ASP.NET controls in a Master Page are automatically reinterpreted relative to the Master Page. This process of reinterpretation is called rebasing. Only ASP.NET control properties decorated with the UrlProperty attribute are rebased.

Second, you can avoid relative URLs and use absolute URLs. For example, if your application is named MyApp, then you can use the following <img> tag to display an image file located in the MasterPages folder:

<img src="/MyApp/MasterPages/Picture.gif" />

The disadvantage of using absolute URLs is that they make it difficult to change the location of a web application. If the name of your application changes, then the absolute URLs will no longer work and you’ll end up with a bunch of broken images and links.

Another option is to use a method to reinterpret relative URLs in a Master Page. For example, the Master Page in Listing 5.10 includes a method named MasterUrl(). This method is used with the <img> tag in the body of the Master Page, which displays the website logo.

Example 5.10. MasterPagesImageMaster.master

<%@ Master Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Public Function MasterUrl(ByVal url As String) As String
        Return String.Format("{0}/{1}", Me.TemplateSourceDirectory, url)
    End Function
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Image Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    <img src='<%=MasterUrl("Logo.gif") %>' alt="Website Logo" />

    <asp:contentplaceholder id="ContentPlaceHolder1" runat="server" />

    </div>
    </form>
</body>
</html>

The Master Page in Listing 5.10 is located in a folder named MasterPages. This folder also includes an image named Logo.gif. This image is displayed with the following HTML tag:

<img src='<%=MasterUrl("Logo.gif") %>' alt="Website Logo" />

The MasterUrl() method appends the image’s filename to the value of the Master Page’s TemplateSourceDirectory property. The TemplateSourceDirectory property represents the folder that contains the Master Page.

The content page in Listing 5.11 uses the Master Page and correctly displays the website logo (see Figure 5.5):

Displaying a Master Page relative image.

Figure 5.5. Displaying a Master Page relative image.

Example 5.11. ImageContent.aspx

<%@ Page Language="VB" MasterPageFile="~/MasterPages/ImageMaster.master" %>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">

    <h1>Content</h1>

</asp:Content>

Registering Master Pages in Web Configuration

You can apply a Master Page to every content page in a particular folder or every content page in an entire application. Rather than add a MasterPageFile attribute to individual content pages, you can add a configuration option to the web configuration file.

For example, the web configuration file in Listing 5.12 applies the SimpleMaster.master Master Page to every page contained in the same folder (or subfolder) as the web configuration file.

Example 5.12. FolderAWeb.Config

<?xml version="1.0"?>
<configuration>
<system.web>
  <pages masterPageFile="~/SimpleMaster.master" />
</system.web>
 </configuration>

The Master Page is applied only to content pages. If a page does not contain any Content controls—it is a normal ASP.NET page—then the Master Page is ignored.

You can override the Master Page configured in the web configuration file in the case of a particular content page. In other words, a MasterPageFile attribute in a content page takes precedence over a Master Page specified in the web configuration file.

Modifying Master Page Content

Master Pages enable you to display the same content in multiple content pages. You’ll quickly discover that you need to override the content displayed by a Master Page in the case of particular content pages.

For example, normally the Master Page contains the opening and closing HTML tags, including the <title> tag. This means that every content page will display the same title. Normally, you want each page to display a unique title.

In this section, you learn multiple techniques of modifying Master Page content from a content page.

Using the Title Attribute

If you only need to modify the title displayed in each content page, then you can take advantage of the <%@ Page %> directive’s Title attribute. This attribute accepts any string value.

For example, the page in Listing 5.13 includes a Title attribute, which sets the title of the current content page to the value Content Page Title.

Example 5.13. TitleContent.aspx

<%@ Page Language="VB" MasterPageFile="~/SimpleMaster.master"
    Title="Content Page Title" %>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
</asp:Content>

<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
</asp:Content>

There is one requirement for the Title attribute to work. The HTML <head> tag in the Master Page must be a server-side Head tag. In other words, the <head> tag must include the runat="server" attribute. When you create a new Web Form or Master Page in Visual Web Developer, a server-side <head> tag is automatically created.

Using the Page Header Property

If you need to programmatically change the Title or Cascading Style Sheet rules included in a Master Page, then you can use the Page.Header property. This property returns an object that implements the IPageHeader interface. This interface has the following two properties:

  • StyleSheet

  • Title

For example, the content page in Listing 5.14 uses the SimpleMaster.master Master Page. It changes the Title and background color of the Master Page.

Example 5.14. HeaderContent.aspx

<%@ Page Language="VB" MasterPageFile="~/SimpleMaster.master" %>
<script runat="server">

    Private Sub Page_Load()
        ' Change the title
        Page.Header.Title = String.Format("Header Content ({0})", DateTime.Now)

        ' Change the background color
        Dim myStyle As New Style()
        myStyle.BackColor = System.Drawing.Color.Red
        Page.Header.StyleSheet.CreateStyleRule(myStyle, Nothing, "html")
    End Sub
</script>
<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
</asp:Content>

<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
</asp:Content>

The Page.Header property returns the server-side <head> tag contained in the Master Page. You can cast the object returned by this property to an HTMLHead control. For example, the page in Listing 5.15 modifies the Master Page <meta>tags (the tags used by search engines when indexing a page).

Example 5.15. MetaContent.aspx

<%@ Page Language="VB" MasterPageFile="~/SimpleMaster.master" %>
<script runat="server">

    Private Sub Page_Load()
        ' Create Meta Description
        Dim metaDesc As New HtmlMeta()
        metaDesc.Name = "DESCRIPTION"
        metaDesc.Content = "A sample of using HtmlMeta controls"

        ' Create Meta Keywords
        Dim metaKeywords As New HtmlMeta()
        metaKeywords.Name = "KEYWORDS"
        metaKeywords.Content = "HtmlMeta,Page.Header,ASP.NET"

        ' Add Meta controls to HtmlHead
        Dim head As HtmlHead = CType(Page.Header, HtmlHead)
        head.Controls.Add(metaDesc)
        head.Controls.Add(metaKeywords)
    End Sub
</script>
<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
    <br />Content in the first column
</asp:Content>

<asp:Content
    ID="Content2"
    ContentPlaceHolderID="ContentPlaceHolder2"
    Runat="Server">
    Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
    <br />Content in the second column
</asp:Content>

Notice that the Page_Load() method in Listing 5.15 creates two HtmlMeta controls. The first control represents a Meta Description tag and the second control represents a Meta Keywords tag. Both HtmlMeta controls are added to the HtmlHead control’s Controls collection.

When the page is rendered, the following tags are added to the <head> tag:

<meta name="DESCRIPTION" content="A sample of using HtmlMeta controls" />
<meta name="KEYWORDS" content="HtmlMeta,Page.Header,ASP.NET" />

Warning

You receive a NullReference exception if you use the Page.Header property when the Master Page does not contain a server-side <head> tag.

Exposing Master Page Properties

You can expose properties and methods from a Master Page and modify the properties and methods from a particular content page. For example, the Master Page in Listing 5.16 includes a public property named BodyTitle.

Example 5.16. PropertyMaster.master

<%@ Master Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Public Property BodyTitle() As String
        Get
            Return ltlBodyTitle.Text
        End Get
        Set(ByVal Value As String)
            ltlBodyTitle.Text = value
        End Set
    End Property
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        html
        {
            background-color:silver;
        }
        .content
        {
            margin:auto;
            width:700px;
            background-color:white;
            padding:10px;
        }
        h1
        {
            border-bottom:solid 1px blue;
        }
    </style>
    <title>Property Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <div class="content">
    <h1><asp:Literal ID="ltlBodyTitle" runat="server" /></h1>
    <asp:contentplaceholder
        id="ContentPlaceHolder1"
        runat="server" />
    </div>
    </form>
</body>
</html>

The BodyTitle property enables you to assign a title that is rendered in a header tag in the body of the page (see Figure 5.6).

Displaying a body title.

Figure 5.6. Displaying a body title.

Because the BodyTitle property is exposed as a public property, you can modify it from a particular content page. The page in Listing 5.17 assigns the value "The Body Title" to the BodyTitle property.

Example 5.17. PropertyContent.aspx

<%@ Page Language="VB" MasterPageFile="~/PropertyMaster.master" %>
<%@ MasterType VirtualPath="~/PropertyMaster.master" %>
<script runat="server">

    Private Sub Page_Load()
        If Not Page.IsPostBack Then
            Master.BodyTitle = "The Body Title"
        End If
    End Sub
</script>
<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content, Content, Content, Content
    <br />Content, Content, Content, Content
    <br />Content, Content, Content, Content
    <br />Content, Content, Content, Content
    <br />Content, Content, Content, Content
</asp:Content>

You should notice several things about the page in Listing 5.17. First, notice that you can refer to the Master Page by using the Master property. In the Page_Load() method in Listing 5.17, the BodyTitle property of the Master Page is assigned a value with the following line of code:

Master.BodyTitle = "The Body Title";

You should also notice that the page in Listing 5.17 includes a <%@ MasterType %> directive. This directive automatically casts the value of the Master property to the type of the Master Page. In other words, it casts the Master Page to the PropertyMaster type instead of the generic MasterPage type.

If you want to be able to refer to a custom property in a Master Page, such as the BodyTitle property, then the value of the Master property must be cast to the right type. The BodyTitle property is not a property of the generic MasterPage class, but it is a property of the PropertyMaster class.

Using FindControl with Master Pages

In the previous section, you learned how to modify a property of a control located in a Master Page from a content page by exposing a property from the Master Page. You have an alternative here. If you need to modify a control in a Master Page, you can use the FindControl() method in a content page.

For example, the Master Page in Listing 5.18 includes a Literal control named BodyTitle. This Master Page does not include any custom properties.

Example 5.18. FindMaster.master

<%@ Master Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        html
        {
            background-color:silver;
        }
        .content
        {
            margin:auto;
            width:700px;
            background-color:white;
            padding:10px;
        }
        h1
        {
            border-bottom:solid 1px blue;
        }

    </style>
    <title>Find Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <div class="content">
    <h1><asp:Literal ID="ltlBodyTitle" runat="server" /></h1>
    <asp:contentplaceholder
        id="ContentPlaceHolder1"
        runat="server" />
    </div>
    </form>
</body>
</html>

The content page in Listing 5.19 modifies the Text property of the Literal control located in the Master Page. The content page uses the FindControl() method to retrieve the Literal control from the Master Page.

Example 5.19. FindContent.aspx

<%@ Page Language="VB" MasterPageFile="~/FindMaster.master" %>
<script runat="server">

    Private Sub Page_Load()
        If Not Page.IsPostBack Then
            Dim ltlBodyTitle As Literal = CType(Master.FindControl("ltlBodyTitle"), Literal)
            ltlBodyTitle.Text = "The Body Title"
        End If
    End Sub
</script>
<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Content, Content, Content, Content
    <br />Content, Content, Content, Content
    <br />Content, Content, Content, Content
    <br />Content, Content, Content, Content
    <br />Content, Content, Content, Content
</asp:Content>

The FindControl() method enables you to search a naming container for a control with a particular ID. The method returns a reference to the control.

Loading Master Pages Dynamically

You can associate different Master Pages dynamically with a content page. This is useful in two situations.

First, you can enable the users of your website to customize the appearance of the website by loading different Master Pages. You can display a menu of Master Pages, and allow your users to pick their favorite layout.

Another situation in which loading Master Pages dynamically is useful concerns co-branding. Imagine that your company needs to make its website look like a partner website. When users link to your website from the partner website, you don’t want users to know that they are traveling to a new website. You can maintain this illusion by dynamically loading different Master Pages based on a query string passed from a partner website.

A Master Page is merged with a content page very early in the page execution life-cycle. This means that you cannot dynamically load a Master Page during the Page Load event. The only event during which you can load a Master Page is during the Page PreInit event. This is the first event that is raised during the page execution life cycle.

For example, the content page in Listing 5.20 dynamically loads one of two Master Pages named Dynamic1.master and Dynamic2.master.

Example 5.20. DynamicContent.aspx

<%@ Page Language="VB" MasterPageFile="~/Dynamic1.master" %>
<script runat="server">

    Protected  Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs)
        If Not Request("master") Is Nothing Then
            Select Case Request("master")
                Case "Dynamic1"
                    Profile.MasterPageFile = "Dynamic1.master"
                Case "Dynamic2"
                    Profile.MasterPageFile = "Dynamic2.master"
            End Select
        End If

        MasterPageFile = Profile.MasterPageFile
    End Sub
</script>

<asp:Content
    ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">

    Select a Master Page:
    <ul class="selectMaster">
        <li>
        <a href="DynamicContent.aspx?master=Dynamic1">Dynamic Master 1</a>
        </li>
        <li>
        <a href="DynamicContent.aspx?master=Dynamic2">Dynamic Master 2</a>
        </li>
    </ul>

</asp:Content>

The page in Listing 5.20 contains two links. Both links include a query string parameter named master, which represents the name of a Master Page. When you click the first link, the Dynamic1.master Master Page is loaded (see Figure 5.7) and when you click the second link, the Dynamic2.master Master Page is loaded (see Figure 5.8).

Displaying the Dynamic1 Master Page.

Figure 5.7. Displaying the Dynamic1 Master Page.

Displaying the Dynamic2 Master Page.

Figure 5.8. Displaying the Dynamic2 Master Page.

Notice that the page in Listing 5.20 includes a Page_PreInit() event handler. This handler grabs the value of the master query string parameter and assigns the value of this parameter to a Profile property. Next, the value of the Profile property is assigned to the page’s MasterPageFile property. Assigning a value to the MasterPageFile property causes a Master Page to be dynamically loaded.

Because the name of the Master Page is assigned to a Profile property, the selected Master Page loads for a user even if the user returns to the website many years in the future. The Profile object automatically persists the values of its properties for a user across multiple visits to a website. The Profile is defined in the web configuration file contained in Listing 5.21.

Example 5.21. Web.Config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <profile>
      <properties>
        <add
          name="MasterPageFile"
          defaultValue="Dynamic1.master" />
      </properties>
    </profile>
  </system.web>
 </configuration>

Loading Master Pages Dynamically for Multiple Content Pages

In the previous section, you learned how to load a Master Page dynamically for a single page in a website. However, what if you need to load a Master Page dynamically for every content page in a website?

The easiest way to apply the same logic to multiple content pages is to create a new base Page class. The file in Listing 5.22 contains a new base Page class named DynamicMasterPage.

Note

Add the file in Listing 5.22 to your application’s App_Code folder.

Example 5.22. DynamicMasterPage.vb

Imports Microsoft.VisualBasic

Public Class DynamicMasterPage
    Inherits Page

    Protected Overrides Sub OnPreInit(ByVal e As EventArgs)
        Me.MasterPageFile = CType(Context.Profile("MasterPageFile"), String)
        MyBase.OnPreInit(e)
    End Sub

End Class

The class in Listing 5.22 inherits from the Page class. However, it overrides the base Page class’s OnPreInit() method and adds the logic for loading a Master Page dynamically.

After you create a new base Page class, you need to register it in the web configuration file. The web configuration file in Listing 5.23 contains the necessary settings.

Example 5.23. Web.config

<?xml version="1.0"?>
<configuration>
  <system.web>

    <pages pageBaseType="DynamicMasterPage" />

    <profile>
      <properties>
        <add
          name="MasterPageFile"
          defaultValue="Dynamic1.master" />
      </properties>
    </profile>
  </system.web>
</configuration>

After you register the DynamicMasterPage class as the base Page class, every page in your application automatically inherits from the new base class. Every page inherits the new OnPreInit() method and every page loads a Master Page dynamically.

Summary

In this chapter, you learned how to share the same content among multiple pages in an application by taking advantage of Master Pages. In the first section, you learned how to create a Master Page and apply it to multiple content pages. You also learned how to nest Master Pages and how to register a Master Page in the web configuration file.

The next section explored various techniques of modifying a Master Page from a particular content page. You learned how to use the Title attribute, how to use the Page.Header property, how to expose properties in a Master Page, and how to use the FindControl() method.

Finally, you learned how you can dynamically load different Master Pages and associate a particular Master Page with a particular content page at runtime. You learned how you can save a user’s Master Page preference by using the Profile object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset