Getting Started with Master Pages and Themes
It seems that there is both excitement and confusion surrounding Master Pages and Themes. A big part of the problem is that they always seem to be mentioned in the same breath – like I just did. The reality is that they are two separate but equally important technologies. Each has its own function in ASP.NET but when you use these two technologies together, you get a site design that is amazingly versatile, easy-to-use, and easy-to-adapt. ASP.NET 2.0 provides a whole host of improvements to your web development experience but, in my opinion, these two technologies represent the single biggest reason to migrate your sites to this new platform. Let's take a look at each of these technologies in turn.
Master Pages gives us visual inheritance for web pages. Take a good look at your web site or web application and pick out those elements that are common to every page in the site. The logo, menu or navigation bar, some links and the footer are probably common to every page. What changes on a page-by-page basis is all that stuff below the menu and just above the footer. Master Pages are the latest and best solution to the question, "How do I share common elements on each page without having to copy and paste the HTML everywhere?" In classic ASP we had include files, which were then superseded by user controls in ASP.NET 1.0/1.1. Includes and user controls are different concepts but both do the same basic job: providing a set of external files that, when included on a page and placed in the correct position, give you a means of attaining a consistent layout for the pages in your website.
That last statement neatly sums up the two main problems with include files and user controls. Firstly, you have to remember to include them and, secondly, you have to put them in the correct spot on each and every page. If you build a site with a couple hundred pages you are almost guaranteed to forget to include a file or misplace it on several pages.
In ASP.NET 2.0, Master Pages supplant user controls and give us true reuse – they allow us to define in a single file, the layout and common features of a whole set of pages, providing a much easier and more maintainable route to consistent look-and-feel.
Creating a basic Master Page
When you migrate your site to ASP.NET 2.0, your first job will be to build one or more Master Pages; one for each distinct layout within your site. To create your first Master Page in Visual Studio 2005, navigate WebSite -Add New Item - Master Page. Give the page a name and it will be added to the project as <yourname>.master.
Notice also the "Place Code in separate file" checkbox: Master Pages support server-side code either in the Page itself or (if that box is checked) in a code-behind partial class.
Partial Classes are another new feature of .NET 2.0. They allow you to create a class definition that spans multiple physical files to make one logical class. ASP.NET employs partial classes for the code-behind files so that ASP.NET can hide the page implementation code that used to appear in the code-behind, with 'Do Not Touch' stamped all over it.
Now all you have to do is define your site's layout in the Master Page. Set up your logo, navigation bar and footer just as you did before using HTML and ASP.NET controls. If you are converting a site, open up those include files or user controls and move your common HTML and control into the Master Page.
Next, you must define the areas in your page layout, the content of which is going to change from on a page by page basis. You do this using a new ASP.NET 2.0 control called the ContentPlaceholder. Each of these controls, when placed on the Master Page, acts as a placeholder for content that may be supplied by each of the "child" content pages that inherits its layout from this page.
Each ContentPlaceholder must have a unique ID. The following Master Page screenshot shows two ContentPlaceholder tags, with IDs of PageName and Main:
Creating a Content Page
To create a Content Page that uses your Master Page, open up Visual Studio 2005 and pull up the Add New Item dialog. This time, though, add a new Web Form to the project. A dialog will then prompt you to select the Master Page that is associated with this new Content Page. When you open the new Content Page all you will see, in place of the classic HTML layout with <html>, <head> and <body> tags, is the Page directive (<% @Page…/>), which points to the appropriate Master Page, and one Content control for each ContentPlaceHolder defined in the selected Master Page. It looks something like this:
Each Content control indicates its associated placeholder via the ContentPlaceHolderID property. Any HTML placed between the opening and closing Content control tags will be placed exactly where the placeholder appears in the Master Page. Please note that all content in child pages must be placed inside a Content control. If you attempt to place content outside a Content> control, you will get an error when you attempt to run the page as the Master Page simply won't know what to do with that content.
Accessing Code in Master Pages
Just as a standard Web Form object is inherited from System.Web.UI.Page so Master Page objects are inherited from System.Web.UI.MasterPage. You can create your own sub-class that from System.Web.UI.MasterPage and then use that class as a parent for your Master Pages. Simply create a new class and have it inherit from System.Web.UI.MasterPage. Add the functionality you need on each Master Page, then open up the code-behind file of each Master Page and change the class it inherits from to your new class. This is useful if your site has mulitple Master Pages that need to have common functionality.
Public properties and classes that are defined in the Master Page (or its code-behind file) can also be accessed by any child Content Page that defines that Master Page in its Page directive. In the following screen, I've delcared a property called MyProperty:
You can now access that property or function from the Content page:
Take a look at Windows Media Player. Change the skin and the entire look and feel of the application changes instantly. The fonts, the graphics and the colors all change. You may not even recognize two different skins as having the same underlying application. Themes bring that power to web. Simply by declaratively setting the Theme property in the Page directive, or imperatively it in code, you can transform your site's entire look and feel.
Themes consist of a skin file and optionally a cascading style sheet. The skin file allows you to define how each type of control (textbox, button, gridview etc.) will be rendered. You can use multiple definitions for each type of control. You can either add your style definition for each control right into the skin file, or you can place those definitions in a cascading style sheet associated with the theme.
Here's a real world look at Themes. The Aesculapius Research Group has a product that allows Othropaedic medical residents at various schools to log their surgical case load on line. The application transfers their case to the ACGME oversite organization and both the resident and the teaching institutions have full access to their cases. One of the features that we were required to build into this application the ability for each instituion to view the application in their colors and logos. This was the perfect application of Themes.
When the resident first comes to the site it is themed in blue and gray – a generic theme that we created. After they log in we swap out the theme to one specific to that institution. For example, when Tulane residents log in, they see a green and blue site with the schools coat of arms in the corner:
Vanderbilt University residents see a Blue and white site with their own shield in the corner, and so on.
Creating a Basic Theme
Start by adding an App_Themes folder to the root of your web project ("Add ASP.NET Folder – Theme"). The App_Themes folder is created and a subfolder called Theme1 is created under it. Rename the Theme1 folder to BlueTheme. Each folder under App_Themes defines a skin. The name of the folder is also the name of the skin. Everything that defines that Theme (.skin, .css, images) is placed in that folder. Additional Theme folders can be added by right- clicking on the App_Themes Folder and again selecting "Add ASP.NET Folder – Theme".
Now right-click on the BlueTheme folder and choose "Add New Item…". Choose "Skin File" and name it BlueTheme.Skin. In the same way, add a stylesheet called BlueTheme.css. If each of your themes is going have a unique set of images assoicated with it you should also create an Images folder under the BlueTheme folder.
On your Content Pages in the header on .aspx page, set the Theme paramater of the Page directive to BlueTheme:
Now, when the page is rendered the theme will be used to set properties on the ASP.NET controls. If you want to set the theme for the entire site you can specify it in the web.config file:
Now, open the BlueTheme.css file and add two style classes:
Open the MyTheme.skin file and add the following code:
<asp:Label runat="server" CssClass="BlueLabel" SkinID="BlueText"></asp>
Note that I have not set a specific SkinID value for RedLabel so the RedLabel style (in the skin file) will be applied to every label on each page that uses this theme that does not have a SkinID set. The second label has a SkinID of BlueText. All labels that have a SkinID of BlueText will use the BlueLabel style settings instead of the default.
That concludes our basic demonstration of themes. However, themes are versatile and I encourage you to experiment with them. You can write skins to control the appearance of any ASP.NET control. For example, you can control the number of columns displayed in a textbox control or control the image that is displayed on a page, based on a theme
In the code download (use link at top of page) included with this article, I've included an example whereby the theme controls the ImageUrl of an image control. This allows you to have specific images with each theme. Change the Theme setting and watch how the ThemeExample.aspx page changes.
Changing Master Pages and Themes
Now that you've applied a Master Page to your web pages and have hard coded a theme, you are probably wondering if you can change them at runtime. Yes, you can. ASP.NET brings us the PreInit event for just this purpose.
Page.MasterPageFile = "MyMaster.Master";
Page.Theme = "BlueTheme";
Page.MasterPageFile = "MySite.Master";
Page.Theme = "RedTheme";
Themes can also be swapped in the PreInit event. In this manner, you could tie the Master Page and the Theme to a user's login. Your site could have a totally different feel for each client, as demonstrated above for the Aesculapius Research Group example.
Many people I've talked don't seem to understand that Master Pages and Themes are two separate technologies.The reason for the confusion between Master Pages and Themes is that these two technologies play so nicely together. When combined, Master Pages and Themes allow us to display a completely different looking site with a completely different layout to each user. Together, these technologies amply fulfill their goal of giving us centralized control over all the common aspsects of our web sites.