Locations of visitors to this page

    Blog List       Minimize  
,NET:ASP:MVP
.NET
.NET 3.5
.NET:ACL
.NET:AppDomains
.NET:ASP
.NET:ASP ServerControls
.NET:ASP:Commerce
.NET:ASP:Config
.NET:ASP:JSON
.NET:ASP:Layout
.NET:ASP:Media/Flash
.NET:ASP:Mobile
.NET:ASP:Monitoring
.NET:ASP:MVC
.NET:ASP:Navigation
.NET:ASP:Stress Testing
.NET:ASP:Validation
.NET:ASP:WebParts
.NET:C#-Trig
.NET:CAB
.NET:CAS
.NET:Certification
.NET:CF
.NET:Collections
.NET:Configuration
.NET:Cryptography
.NET:Db
.NET:Delegates
.NET:Deployment
.NET:Diagnostics
.NET:Documentation
.NET:Encoding
.NET:Environment
.NET:Extension Methods
.NET:Globalization
.NET:I/O Streams
.NET:Interop
.NET:IO:Mail
.NET:IsolatedStorage
.NET:LicenseManager
.NET:LINQ
.NET:Metrics/Quality
.NET:Mono
.NET:MSOffice
.NET:Optimization
.NET:Patterns/Practices
.NET:Phone7
.NET:Reflection
.NET:Remoting
.NET:Reverse Engineering
.NET:Serialization
.NET:Silverlight
.NET:Silverlight UserGroup
.NET:Silverlight:Phone7
.NET:Threading
.NET:WCF
.NET:Windows Services
.NET:WinForms
.NET:WPF
.NET:Xml
Admin
Admin:Creating Software
Admin:CruiseControl
Admin:Estimating
Admin:Installers/Packaging
Admin:Methodologies
Admin:PM
Admin:SourceControl
Admin:UnitTesting
Admin:VisualStudio
Arch:Gen
Arch:Patterns
Arch:UML
Blogging
DB:Sqlite
DB:SqlServer
DB:SqlServer CE
DB:VistaDB
Graphs
IT
IT:DNN
IT:DOS
IT:IIS
IT:MailServers
IT:MS Office
IT:OS (XP/Vista/7)
Misc
Misc:Hardware
Misc:Humour
mISV:Accounting
mISV:Marketing
OS:Vista
Personal
Personal:Children
Personal:Faith
Personal:Family
Personal:History
Personal:Politics
Places:New Zealand
Places:Paris
Presentations
Tech:CSS
Tech:Regex
Tech:SQL
Tech:Web:HTML
Tech:XML/XSL
Web:HTML5

             
    Sprouting Synapses       Minimize  

             
All about ASP.NET Master/Content Pages, Themes, etc.

Note that posts regarding WebParts are kept separate since that's a pretty large subject in its own right...

Themes Themes in ASP.NET (since 2.0) are similar to cascading style sheets (CSS) in that both themes and style sheets define a set of common attributes that can be applied to any page.

However, themes differ, and are more powerful, than style sheets because Themes can define many properties of a control or page, not just style properties. For example, using themes, you can specify a Button's Text, the graphics for a TreeView control, the template layout of a GridView control, and so on,as well as setting the CSS class property for each control.

A Summary In essence, we're talking about creating named folders ("Default", "WhiteOnBlack", "Silver", "WaterBlue", etc.) within the website's App_Themes system folder, within which will be all the resources needed to create the look of a website. This means each Theme folder will contain one or more css files, images, and *.skin files. Each *.skin file will in turn contain one or more template control definitions, more commonly known as control skins (note the terminology: we are talking about "control skins", within "skin files") These control skin definitions will be either default control templates (ie do not have a SkinID attribute) that are applied to all Controls of the same type, or they are named control skins, which are only applied to controls of the same type that also have the same SkinID attribute value. These skins are applied to Pages by applying the Theme or StyleSheetTheme attribute to the Page declaration tag,

In case all or most of the above was Chinese to you, lets go through each part, one by one.

Theme A Theme is simply a a collection of assets required to create a "look" for a website. This will include css files, images, and -- most importantly -- skin files.

Theme Folders: A Theme is defined simply by creating a subfolder within the website's special App_Themes folder, within which you place any assets you will need to create the look of the website (css, images, skin files).  Since we're generally comfortable with css and images, we'll concentrate directly to the skin files.

image

Skin Files: There is no hard set rule on how to set up control skins: within the theme folder you can create a separate file for each control (button.skin, label.skin, etc.) or define one single skin file (eg: site.skin) within which all the control skin definitions exist (I generally use one per control, but its up to you of course).

What the skin file is called is unimportant (default.skin is fine, so is whatever.skin), its the control skin definitions within the file(s) that is parsed and therefore important.

Control Skins/Definitions: Within the skin files, you add control skins (control templates).  These come in two flavors:

default control skins (ie, do not have a SkinID attribute). A default skin is automatically applied to all controls of exactly the same type, when a theme is applied to a page. For example, if you create a default control skin for a Button control, the control skin applies to all Button controls on pages that use the theme. asp:button runat="server" BackColor="#F0F0FF" ForeColor="darkblue" />

named control skins (ie, do has a SkinID attribute defined). Named skins do not automatically apply to controls by type. Instead, you explicitly apply a named skin to a control by setting the control's SkinID property. Creating named skins allows you to set different skins for different instances of the same control in an application. asp:Button runat="server" BackColor="#F0F0FF" ForeColor="darkblue" SkinID="GoButtons" />

Either way, default, or named:

Each control skin/definition must have the runat attribute. Each control skin/definition must not have the ID attribute. You can have only one default control skin per control type, but as many as you want named control skins -- as long as they have different SkinID values.  

 

Apply Themes to Pages and their Controls Once one or more Themes have been defined, all that's left to do is apply them to the pages and the controls on them.

The difference between the theme and styleSheetTheme attributes:

You can attach themes to pages with either the Theme attribute or StyleSheetTheme attribute:



or



Why two different ways? Good question.

If you use theme the properties set in the control skin override local control settings.  In other words, if your default control skin for Button controls has the Text property set to "OK", guess what happens....right: every themed button will now show "OK", even if it was defined with another Text.

If you use styleSheetTheme to attach the theme, only settings from the control skin that are not explicitly set on the control itself, are set.

Which one should you choose? Microsoft, in their 70-547 self-prep book suggests that you use it with caution -- but, personally, I prefer StyleSheetTheme, because it mirrors better what I am used to with standard CSS (where one defines a base CSS style sheet, and override it locally for exceptional cases). Of course, the final choice is up to you.

Apply a Theme to all Pages:

configuration> system.web> ... pages StyleSheetTheme="WhiteOnBlack"> ... pages> system.web> configuration>

Apply a Theme to a Single Page:

Or you can do it per page, by adding the Theme attribute to the declarations:



Applying Themes to Controls: Within the page, you can use a control as you normally would, and it will use the default control skin if there is one:

asp:Button runat="server" ID="SomeButton" />

Or refer back to a named control skin simply by using the SkinID:

asp:Button runat="server" ID="SomeButton" SkinID="GoButton" />

 

Dynamically Changing Themes You can update the page's theme in the PreInit event as shown here:

protected void Page_PreInit(Object sender, EventArgs e) { //Reminder: won't work: PreInit happens before controls generated: this.Theme = wc.ThemeName.Text; if (Session["MySiteTheme"]==null){ //use whatever was set on page declaratively. }else{ //Will Work: this.Theme = Session("MySiteTheme").ToString(); //as long as Session value set somewhere earlier... } }

But you'll notice that if no controls were created yet, you can't refer to a value from a DropDownList or any other control. Instead, what you have to do is set the Session property from an event of the DropDownList, and redirect to the same page:

protected void wcThemes_SelectedIndexChanged(object sender, EventArgs e) { //Save in Session (not just Context.Items): Session.Add("MySiteTheme", wcThemes.SelectedValue); //Transfer to exact same page: Server.Transfer(Request.FilePath); }

How do you get the list of items to put in the DropDownList easily? Like this:

Which you can bind to your DropDownList as follows:

asp:DropDownList runat="server" ID="wcThemes" DataTextField="name" DataValueField="name" OnDataBound="wcThemes_DataBound" DataSourceID="ThemeDataSource" OnSelectedIndexChanged="wcThemes_SelectedIndexChanged" AutoPostBack="true"/> asp:ObjectDataSource runat="server" ID="wcThemeDataSource" TypeName="MyThemeManager" SelectMethod="GetThemes"/>

The above ObjectDataSource is bound to the result of a static method that returns a list of Themes:

//using System.IO; //using System.Web; public class MyThemesManager { public static Liststring> GetThemes() { DirectoryInfo appThemesDirInfo = new DirectoryInfo( HttpContext.Current.Server.MapPath("App_Themes")); DirectoryInfo[] directoryInfo = appThemesDirInfo.GetDirectories(); List themes = new List(); foreach (DirectoryInfo directoryInfo in directoryInfos){ Theme theme = new Theme(directoryInfo.Name); list.Add(theme); } return themes; } //Which refers to a simple one field class //just for binding purposes: public class Theme{ public string Name{ get { return _Name; } set { _Name = value; } } private string _Name; public Theme(string name){_Name = name;} } }

One last detail:

protected void wcThemes_DataBound(object sender, EventArgs e) { //set the value to the current theme: wcThemes.SelectedValue = Page.Theme; }

 

Note: A question that comes up often is why the Page_PreInit event has to be in a Content Page, and can't be moved to a master page. The answer is that a Master Page doesn't have a Page_PreInit event that can be used. A solution is to move the code to a base Page, or do it in an HttpModule (a link is given below).

Tips For ASP.NET to be able to automatically add a LINK for the theme's css file to the current page, the Page's HEAD element must have a runat=server on it.

 

Summary Now that you've read all the above, the following notes, summarizing what you need to remember to get up and going quickly, should all make sense:

Creating Skins Files and Control Skins: You create Themes simply by creating named folders (BlackOnWhite, Silver, etc.) in the website's  special App_Theme folder. Within these theme folders you add all assets needed to create a 'look' for the website. This includes images, css, and one or more skin files. Within each skin file, you define one or more default, and (optionally) named, control skins (ie the control templates). Each control skin/definition must have the runat attribute, or you'll get an error stating that skins can't contain literal text. Each control skin/definition must not have an ID attribute -- so if you copy/paste your template from a real page, remember to remove ID attributes. Note that Control Skins are matched exactly by Control Type: a Button skin applies to Buttons -- not LinkButton, nor any control that descends from Button.Note that you can have only one default control skin per control type, but as many as you want named control skins -- as long as they have different SkinID values   Applying Themes: Use either a Theme or StyleSheetTheme attribute to wire up a theme: Use the Theme attribute for the Control Skin's properties to override/crush any settings set on the page. Use the StyleSheetTheme if you want the Control Skin's properties to merge with the page's control's settings, leaving any in place that were set on the page. If a control has a SkinID attribute, but a named control skin of the same name cannot be found in the theme (this can easily happen by adding a named control skin to one theme, and forgetting to add the same control skin definition to the other themes) it will fall back to the default control skin. In addition, if there is no default control skin defined, no skinning will occur at all -- either way, no exception will be raised. The Attribute to theme a control to specific Control Skin is also SkinID -- exactly the same attribute as used in Control Skin definitions (maybe its just me, but I've always found that duplicate use of exactly the same attribute name in two different contexts slightly disconcerting. But really no biggie). Note that only one theme can be applied to each page. You cannot apply multiple themes to a page, unlike style sheets where multiple style sheets can be applied. Ensure the Page HEAD element is configured as a runat="server".  

Links:

ASP.NET Themes and Skins Overview How to- Define ASP.NET Page Themes (Visual Studio) http://blogs.vertigosoftware.com/alanl/archive/2006/09/11/Theme_vs_StyleSheetTheme.aspx Disable Theming and StyleSheet theme for one specific page in Asp.Net 2.0 ScottGu: Recipe: Dynamic Site Layout and Style Personalization with ASP.NET http://www.codeproject.com/KB/aspnet/dynamicThemes.aspx (better) http://www.codeproject.com/KB/aspnet/themeswitcher.aspx?df=100&forumid=292951&select=1983760&msg=1983760 (using an HttpModule) ...

Read More »

I've just come back from perusing an article talking about MasterPages that went on and on and on...and then on and on some more......
And frankly, I didn't see the point of it all: MasterPages are much simpler than that in practice.

Create a MasterPage template

A MasterPage is a page that defines a master layout, within which are zones/slots/placeholders for content that you will define in ContentPages (see below).

You make a MasterPage by the following process:

  • Tip: Start off right, by creating a root directory called MasterPages (or anything other name you want), to keep your master pages together.
  • In this designated MasterPages folder, create a new page (an *.aspx).
  • Change the file extension from .aspx to .master
  • Change the page's <%@ Page %>declaration to a <%@ Master%>declaration.
  • Add one or more asp:contentplaceholder elements, each with a defined id.
    • These are the named zones/areas where content (defined later in ContentPages) will go.
  • Default Content can be placed within an asp:ContentPlaceHoder, as is demonstrated in the above footer.
<%@ Master Language="C#" %> 

<html> 
  <head runat="server"> 
    <title>The PlaceHolder For Title Set In Content Pagetitle> 
  head> 
  <body> 
    <form id="form1" runat="server"> ?
      <div><asp:contentplaceholder id="Header" runat="server" />div>
      <div><asp:contentplaceholder id="Body" runat="server" />div>
      <div>
        <asp:contentplaceholder id="Footer" runat="server">
          Any default text/markup you care for, 
          in case no content is defined.
        asp:contentplaceholder>
      div>
    form> 
  body> 
html>

Create one or more ContentPages for the above MasterPage:

  • Start a new page anywhere in your site
    • Note: Obviously, not in your MasterPages folder -- which is for MasterPages only.
      For this example, let's just do in the base directory.
  • Add a MasterPageFile attribute to the <%@ Page %>declaration, pointing to the above MasterPage (or another).
  • Add a Title attribute to the <%@ Page %>declaration.
    • Note: This will be the used to set the MasterPage's
Copyright 2007 by Sky Sigal