Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]
.pdf
C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S |
539 |
Studio design environment. Adding to the disappointment was that Windows Forms (the .NET toolkit for Windows user interfaces) included a model for reusable form templates, although even that was far from perfect. Finally, ASP.NET 2.0 fills the gap with a comprehensive new feature called master pages.
To provide a practical, flexible solution for page templating, a number of requirements must be met:
•The ability to define a portion of a page separately and reuse it on multiple pages.
•The ability to create a locked-in layout that defines editable regions. Pages that reuse this template are then constrained to adding or modifying content in the allowed regions.
•The ability to allow some customization of the elements you reuse on each page.
•The ability to bind a page to a page template declaratively (with no code) or to bind to a page dynamically at runtime.
•The ability to design a page that uses a page template with a tool such as Visual Studio.
Master pages meet all of these requirements. They provide a system for reusing templates, a way to limit how templates can be modified, and rich design-time support.
For this to work, ASP.NET defines two new types of pages: master pages and content pages. A master page is a page template. Like an ordinary ASP.NET web page, it can contain any combination of HTML, web controls, and even code. In addition, master pages can include content placeholders—defined regions that can be modified. Each content page references a single master
page and acquires its layout and content. In addition, the content page can add page-specific content in any of the placeholders. In other words, the content page fills in the missing pieces that the master page doesn’t define.
For example, in a typical website, a master page might include a fixed element such as a header and a content placeholder for the rest of the page. The content page then acquires the header for free and supplies additional content.
To take a closer look at how this works, it helps to consider the example presented in the following sections.
A Simple Master Page
To create a master page in Visual Studio, select Website Add New Item from the menu. Select Master Page, give it a filename, and click OK.
A master page is similar to an ordinary ASP.NET web form. Like a web form, the master page can include HTML, web controls, and code (either in an inline script block or in a separate file). One difference is that while web forms start with the Page directive, a master page starts with a Master directive that specifies the same information, as shown here:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="SiteTemplate.master.cs" Inherits="SiteTemplate_master" %>
Another difference between master pages and ordinary web forms is that master pages can use the ContentPlaceHolder control, which isn’t allowed in ordinary pages. The ContentPlaceHolder is a portion of the page where the content page can insert content. When you create a new master page in Visual Studio, you start with a blank page that includes a single ContentPlaceHolder control (see Figure 15-9), although you can add as many as you need.
540 C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S
Figure 15-9. A new master page
The ContentPlaceHolder doesn’t have any remarkable properties. Here’s an example that creates a master page with a static banner followed by a ContentPlaceHolder and then a footer (shown in Figure 15-10):
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="SiteTemplate.master.cs" Inherits="SiteTemplate_master" %>
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<title>Untitled Page</title> </head>
<body>
<form id="form1" runat="server"> <table width="100%">
<tr>
<td bgcolor="black" style="...">
<img align="left" src="headerleft.jpg" /> <img align="right" src="headerright.jpg" /> <br />My Site<br />
</td>
</tr>
</table> <br />
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder>
<br />
<em>Copyright © 2005.</em> </form>
</body>
</html>
C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S |
541 |
Figure 15-10. A master page at design time
Master pages can’t be requested directly. To use a master page, you need to build a linked content page.
A Simple Content Page
To use your master page in another web page, you need to add the MasterPageFile attribute to the Page directive. This attribute indicates the filename of the master you want to use:
<%@ Page Language="C#" MasterPageFile="~/SiteTemplate.master" ... %>
Notice that the MasterPageFile attribute begins with the path ~/ to specify the root website folder. If you just specify the filename, ASP.NET checks a predetermined subfolder (named MasterPages) for your master page. If you haven’t created this folder or your master page isn’t there, it checks the root of your web folder next.
Setting the MasterPageFile attribute isn’t enough to transform an ordinary page into a content page. The problem is that content pages have a single responsibility—to define the content that will be inserted in one or more ContentPlaceHolder controls (and to write any code you need for these controls). A content page doesn’t define the page, because the outer shell is already provided by the master page. As a result, attempting to include elements such as <html>, <head>, and <body> will fail, because they’re already defined in the master page.
To provide content for a ContentPlaceHolder, you use another specialized control, called Content. The ContentPlaceHolder control and the Content control have a one-to-one relationship. For each ContentPlaceHolder in the master page, the content page supplies a matching Content control (unless you don’t want to supply any content at all for that region). ASP.NET links the Content control to the appropriate ContentPlaceHolder by matching the ID of the ContentPlaceHolder with the Content.ContentPlaceHolderID property of the corresponding Content control. If you create a Content control that references a nonexistent ContentPlaceHolder, you’ll receive an error.
C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S |
543 |
To get a better understanding of how master pages work under the hood, it’s worth taking a look at a content page with tracing (add the Trace="True" attribute in the Page directive). That way you can study the control hierarchy. What you’ll discover is that ASP.NET creates the control objects for the master page first, including the ContentPlaceHolder, which acts as a container. It then adds the controls from the content page into the ContentPlaceHolder.
Design-Time Quirks with Master Pages
The design-time representation of your content pages can range from excellent to poor. For the simple header and footer example, you’ll see a fairly good representation of your content page that includes all the elements of the master page and the additional content you’ve added. The parts you’ve acquired from the master page will be shaded in gray, indicating you can’t select or change them in any way. Instead, you’ll be limited to inserting comments into the ContentPlaceHolder region, as shown in Figure 15-12.
Figure 15-12. A content page at design time
■Tip If a master page defines a ContentPlaceHolder but your content page doesn’t define a corresponding Content control, you’ll see a black box in its place. To add the required Content control, right-click that section of the page and choose Create Custom Content.
However, this design-time representation is a little misleading. That’s because when you run the page, the ContentPlaceHolder section will expand or collapse to fit the content you place in it. If you’ve added volumes of text, the footer won’t appear until the end. And if you’ve included only a single line of text, you’ll see something more compact (as in Figure 15-11).
The main problem is how Visual Studio renders the ContentPlaceHolder and Content controls. Initially, these are shown as empty boxes that expand as you add content. However, no matter how little content you add, the design-time representation of this box won’t shrink beyond a certain set size. As a result, your alignment won’t be faithfully depicted for very small content regions.
544 C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S
To see a more dramatic example of this problem, try adding a second ContentPlaceHolder to the master and allowing the user to define a title in the header, with the preset graphics and font:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="SiteTemplate.master.cs" Inherits="SiteTemplate_master" %>
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<title>Untitled Page</title> </head>
<body>
<form id="form1" runat="server"> <table width="100%">
<tr>
<td bgcolor="black" style="...">
<img align="left" src="headerleft.jpg" /> <img align="right" src="headerright.jpg" /> <br />
<asp:ContentPlaceHolder id="TitleContent" runat="server"> </asp:ContentPlaceHolder>
<br /> </td>
</tr>
</table> <br />
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder>
<br />
<em>Copyright © 2005.</em> </form>
</body>
</html>
Now you can easily set the banner text in the content page by adding a second Content control:
<%@ Page Language="C#" MasterPageFile="~/SiteTemplate.master" AutoEventWireup="true" CodeFile="SimpleContentPage.aspx.cs" Inherits="SimpleContentPage_aspx" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<span style="...">Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy lies a small unregarded yellow sun.</span> </asp:Content>
<asp:Content ContentPlaceHolderID="TitleContent" ID="Content2" runat="server"> Custom Title</asp:Content>
Figure 15-13 compares what you’ll see at design time with what you’ll see at runtime. Not only is the text unreadable (because the white font color from the master page isn’t applied at design time), but also the layout is scrambled because of the minimum display size that the Content control uses at design time.
C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S |
545 |
Figure 15-13. The design-time and runtime view of a more complex content page
■Tip When creating master pages that don’t use tables, make sure you include a <br /> line break after your ContentPlaceHolder, if needed. In the design environment, the ContentPlaceHolder is shown as a box that takes the full width of the design surface. As a result, content that appears after it always starts on the line underneath. However, if you haven’t added a line break, in your content page you’ll see a different behavior—namely, the content in the ContentPlaceHolder placeholder will run directly into the following content.
546 C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S
Default Content
When the master page defines a ContentPlaceHolder, it can also include default content—content that will be used only if the content page doesn’t supply a corresponding Content control.
To get this effect, all you need to do is place the appropriate HTML or web controls in the ContentPlaceHolder tag. (You can do this by hand using the .aspx markup or just by dragging and dropping controls into the ContentPlaceHolder.)
Here’s an example that adds default content to the banner text from the previous example:
<asp:ContentPlaceHolder id="TitleContent" runat="server"> Master Pages Website
</asp:ContentPlaceHolder>
If you create a content page in Visual Studio, you won’t notice any immediate change. That’s because Visual Studio automatically creates a <Content> tag for each ContentPlaceHolder. When a content page includes a <Content> tag, it automatically overrides the default content. However, if you delete the <Content> tag, you’ll see the default content in its place—the new “Master Pages Website” banner text.
■Note Content pages can’t use just a portion of the default content or just edit it slightly. This isn’t possible because the default content is stored only in the master page, not in the content page. As a result, you need to decide between using the default content as is or replacing it completely.
A More Practical Master Page
For the most part, HTML uses a flow-based layout. That means as more content is added, the page is reorganized and other content is bumped out the way. This layout can make it difficult to get the result you want with master pages. For example, if you aren’t careful, you could craft the perfect layout, only to have the structure distorted by a huge block of information that’s inserted into a <Content> tag.
To control these problems, most master pages will use either HTML tables or CSS positioning to control the layout.
With tables, the basic principle is to divide all or a portion of the page into columns and rows. You can then add a ContentPlaceHolder in a single cell, ensuring that the other content is aligned more or less the way you want. With CSS positioning, the idea is to separate your content into <div> tags and position these <div> tags by using absolute coordinates or by floating them on one side of the page. You’ll then place the ContentPlaceHolder in the <div> tag.
■Tip For some great examples of CSS-based layout, see the sites http://www.csszengarden.com and http://www.bluerobot.com/web/layouts.
The following example shows how you can use master pages to create a traditional web application with a header, footer, and navigation bar, all of which are defined with tables. Figure 15-14 shows how this structure is broken up into a table.
C H A P T E R 1 5 ■ T H E M E S A N D M A S T E R PA G E S |
547 |
Figure 15-14. A table-based layout |
|
Here’s the markup for the table:
<table width="100%">
<tr><td colspan="2">My Header</td></tr> <tr>
<td width="150px">Navigation Controls</td> <td>
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder>
</td>
</tr>
<tr><td colspan="2">My Footer</td></tr> </table>
■Tip To a quick refresher on HTML tables, complete with information about how to specify borders, cell sizes, alignment, and more, refer to the examples at http://www.w3schools.com/html/html_tables.asp.
Figure 15-15 shows the resulting master page and a content page that uses the master page.
To convert this example into something more practical, just replace the static text in the master page with the actual header, navigation controls, and footer you really want. All the child pages will acquire these features automatically. This is the first step for defining a practical structure for your entire website.
