Programming Microsoft Web Forms (Pro Developer)
After you have created a few Web Forms for a site, it will become apparent that a great deal of common markup is used on every page. You can see such common markup in several of the examples in this chapter that use HTML tables and cascading style sheets for page layout. But if we wanted to create a site with several Web Forms that share a common look and feel, doing so the way in which we have done it so far would be tedious.
In Classic ASP, the solution to this problem was server-side includes. By using include files containing markup (and possibly code), developers could create, with some difficulty, pages that could take on an overall look and feel. ASP.NET 1.x changed the model for handling common page elements. Rather than server-side includes, user controls were the preferred way to create reusable blocks of markup and code. The user control has its own event model that mirrors the event model of the page. This was a workable model, but there were limitations. For example, you had to manually add the user control or controls providing the boilerplate markup and code to each page. Often, several user controls were needed (one for the header, one for the menu, one for the footer, and so on).
ASP.NET 2.0 offers a much better solution. Master Pages can be created in a way similar to creating a normal Web Form. A Master Page contains the markup for a page, in addition to one or more contentplaceholder tags that can contain default content, which can be modified by the pages that use the Master Page. Table 3-1 lists important properties of the MasterPage class.
Member Name | Description |
---|---|
ContentPlaceholders | A property that gets a list of contentplaceholder controls that the Master Page uses to define different content regions. |
Master | A property that gets the parent Master Page of the current Master Page, when Master Pages are nested. |
Note | Although it is completely legal in ASP.NET 2.0 for a Master Page to itself have a Master Page (and there might be particular scenarios that are best served by nesting Master Pages), this is not supported in Design view in Visual Studio. After trying to use nested Master Pages in Visual Studio, I found this limitation to be significant enough that I do not use nested Master Pages. |
To create a Master Page in Visual Studio, right-click the Web site and select Add New Item. In the Add New Item dialog box, select Master Page, enter a name, and then click Add. The Add New Item dialog box is shown in Figure 3-24.
Listing 3-5 shows the markup for the Master Page created by Visual Studio.
Listing 3-5: MasterPage.master Template Content
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> <!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 runat="server"> <title>Untitled Page</title> </head> <body> <form runat="server"> <div> <asp:contentplaceholder runat="server"> </asp:contentplaceholder> </div> </form> </body> </html>
The @ Master directive looks very similar to the @ Page directive seen previously, and the attributes have similar meaning. Inside the form tags is a comtentplaceholder control, with a name of ContentPlaceHolder1. In most cases, I kept the default value provided by Visual Studio for the control IDs. This particular ID is used not only in this Master Page, but also as a link from any page that uses this Master Page. Thus, a meaningful name is important.
Using the cascading style sheets layout from CSSLayout2.aspx as a base, I modified MasterPage.master (from Listing 3-5) so that it contained the same layout as CSSLayout2.aspx. Listing 3-6 shows the resulting markup.
Listing 3-6: MasterPage.master with Layout like CSSLayout2.aspx
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> <!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 runat="server"> <title>Master Page</title> <link href="StyleSheet2.css" rel="stylesheet" type="text/css" /> </head> <body> <form runat="server"> <div >Menu</div> <div >Banner</div> <div > <asp:contentplaceholder runat="server"> Main Content. This is the default text from the master page. </asp:contentplaceholder> </div> </form> </body> </html>
The markup in Listing 3-6 should look familiar. Between the form tags, the markup is almost identical to CSSLayout2.aspx, with the addition of the contentplaceholder tag. Text and markup placed inside the contentplaceholder tag are used as default content when the page using the Master Page does not provide content for that contentplaceholder tag. When viewed in Visual Studio in Design view, the screen appears as shown in Figure 3-25.
You can drag components onto the form and edit existing text, just as you can when editing a Web page. After you create a Master Page, you have the option of selecting a Master Page whenever you create a new Web page. When you create a new Web page (by right-clicking the Web site in Solution Explorer and selecting Add New Item), note the Select Master Page check box toward the bottom of the Add New Item dialog box, as shown in Figure 3-26.
When you enter the file name you want to use (in this case, CSSLayout2WithMaster.aspx) and click Add, a dialog box appears that allows you to select a Master Page, as shown in Figure 3-27.
The Master Pages in the project are available in this dialog box, and you should select one from the list. What is most revealing about the markup in the newly created page is its brevity.
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="CSSLayout2WithMaster.aspx.cs" Inherits="CSSLayout2WithMaster" Title="Untitled Page" %> <asp:Content ContentPlaceHolder Runat="Server"> </asp:Content>
The markup is wrapped here for clarity, but it is on three separate lines in the file. Most of the attributes of the @ Page directive should be familiar by now; however, there is one noteworthy addition. The MasterPageFile attribute allows you to specify the Master Page to use for the page. The only other markup is a single Content tag, already linked to the contentplaceholder tag in the Master Page from Listing 3-6.
In Design view, a Web Form with a Master Page allows editing and dragging components only onto the area defined in the Content tag. The rest of the screen is locked, which makes complete sense, because when editing a page based on a Master Page, you should be able to modify only the content that is on that page. CSSLayout2WithMaster.aspx is shown in Design view in Figure 3-28.
Because there is no text inside the Content tag in CSSLayout2WithMaster.aspx, the main content area of the form will be blank when the page is run. If, rather than leaving the Content tag without text, you deleted the tag entirely (leaving just the @ Page directive in the markup), the default content from the Master Page would appear as shown in Figure 3-29.
Of course, a more useful example of using a Master Page is the creation of custom content to add to the Content tags that overrides the default content from the Master Page. By dropping in some markup similar to that in SimpleWebForm.aspx, the resulting markup in CSSLayout2WithMaster.aspx is as shown in Listing 3-7.
Listing 3-7: CSSLayout2WithMaster.aspx
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="CSSLayout2WithMaster.aspx.cs" Inherits="CSSLayout2WithMaster" Title="Untitled Page" %> <asp:Content ContentPlaceHolder Runat="Server"> <table width=100% border=1> <tr> <td align=right width=50%> <asp:Label runat="server" Text="Text Box:"> </asp:Label></td> <td> <asp:TextBox runat="server"></asp:TextBox></td> </tr> <tr> <td align=right width=50%> <asp:Label runat="server" Text="Drop Down List:"> </asp:Label></td> <td> <asp:DropDownList runat="server"> <asp:ListItem>Red</asp:ListItem> <asp:ListItem>Green</asp:ListItem> <asp:ListItem>Blue</asp:ListItem> </asp:DropDownList></td> </tr> <tr> <td align=right width=50%> <asp:Label runat="server" Text="List Box:"> </asp:Label></td> <td> <asp:ListBox runat="server"> <asp:ListItem>Red</asp:ListItem> <asp:ListItem>Green</asp:ListItem> <asp:ListItem>Blue</asp:ListItem> </asp:ListBox></td> </tr> <tr> <td align=center colspan=2></td> </tr> </table> </asp:Content>
The great thing about using Master Pages is that each page has only the markup required for that page. By factoring out all common markup and functionality, the developer is better able to focus on what is important the unique content on the page.
When run, CSSLayout2WithMaster.aspx looks like Figure 3-30.
The Master Page examples here use only markup. The real power in Master Pages can be seen when, in addition to visual features, common code is also included in the Master Page. For instance, I created a Master Page that includes buttons and button handlers that allow all standard CRUD code (Create, Read, Update, and Delete) to reside in the Master Page, with the page that uses the Master Page required only to set a few properties.
Sometimes, it might be useful to refer to properties or methods of the Master Page from the page using it. The Page class has a Master property so that from a page, you can refer to the Master Page in code by referencing the Master property of the current page.
If you are trying to get to a custom property or method of the Master Page rather than some standard property, you must cast the Master property to the correct type. For instance, if you have a Master Page in which the class is named MyMasterPage, you can access an instance of the class like so.
MyMasterPage myMaster=(MyMasterPage)this.Master;