Themes

Themes provide a way to customize the look and feel of your site, including graphics, CSS styles, properties, and so on. Not only does this provide a way for you, the developer, to provide a consistent style, but it also allows the users to select the style. While this may not be required in every Web site, using themes does allow for consistency among pages and controls, giving an easy way to change the look of the site even if this isn't a user requirement.

The great beauty of the way themes work is that there are very few changes required to an ASP.NET page for them to be used. This means that from the development perspective, the work involved is minimal. Once theme support is included in a site or page, the addition, change, or removal of themes is simple, since themes are stored external to the pages themselves . To understand themes you have to understand the terminology and how it is applied within ASP.NET.

Themes and Skins

The theme architecture defines two terms themes and skins . A skin defines the visual style applied to a control, such as the stylesheet attributes, images, colors and so on. A theme is a collection of skins and applies to an ASP.NET page. Themes are stored under the Themes directory under the application root, with a directory for each theme. Within the directory for a theme there is a file for the theme itself (containing the skin details for each control), stylesheets, and any images required for controls (e.g., images for the TreeView control).

Each theme can have a default look, where no skin is specified, or there can be multiple skins within each theme. This allows you to have themes that are distinct from each other and have multiple looks. For example, you could have a theme called Pastel and within it skins called Pink and Blue .

A theme doesn't have to provide a skin for every server control. Any controls that have no skin within the theme file will use the default look supplied by the browser (or as overridden by a stylesheet). For consistency, however, it is better to provide a skin for each control you use. Setting the skin for a control where no skin exists for that control type will generate an error.

You can use skins to do more than provide just a single look for the entire site. Skins are uniquely identified by the SkinID property applied to the control in a skin file, allowing the same control to be duplicated in the skin file with different SkinID values. This allows, for example, the same type of control to be used on different pages but to have a different look on each page. Theming can also be disabled at both the page and control levels, so page developers aren't forced to use themes.

Global Themes

In addition to theme support on a local application level, the Framework supports global themes, which are available to all applications. These are initially installed in the { windows } \Microsoft.Net\Framework\ {version} \ASP.NETClientFiles\Themes directory and then copied to the Web root ( Inetpub\ wwwroot \aspnet_client\ {version} \Themes ). Local themes with the same name as a global theme replace the global theme in its entiretyno merging with or inheritance from the global theme takes place.

The Technology Preview release initially ships with two global themes, BasicBlue and SmokeAndGlass , but several more are planned for beta releases. As an example, login controls using these two global themes are shown in Figure 7.6.

Figure 7.6. BasicBlue (left) and SmokeAndGlass (right) themes

graphics/07fig06.gif

Creating Themes

To create local themes, you simply create a directory called Themes under your application root, then create a directory for each theme. For example, consider Figure 7.7, where a theme called Basic has been created. The skin details for the theme are in the file called Basic.skin .

Figure 7.7. The directory and file for a simple theme

graphics/07fig07.gif

The name of the skin file doesn't have to match that of the theme, although for the default skin this makes sense. Any images relating to this theme can be placed either in the Themes directory itself or in a separate directory, as shown in Figure 7.7.

The contents of the skin file are simply control declarations. For example, the default skin for Basic has the following code:

 <asp:Label runat="server"     ForeColor="#FFFFFF" BackColor="#660000" /> 

This simply defines a single control, with white text on a red background. When the theme of a page is set to Basic , all Label controls will inherit this style. Since no other controls are defined in this skin they will use either the default HTML settings or those supplied by a stylesheet.

Creating Skins

An explicitly named skin is created by supplying a SkinID property on the controls in the skin file. For example:

 <asp:Label runat="server" SkinID="Red"     ForeColor="#FFFFFF" BackColor="#660000" /> 

Here the SkinID is set to Red . This wouldn't, therefore, be part of the default skin (which has no SkinID ), and its look has to be explicitly set on a control within a page.

SkinIDs must be unique for each control, so you cannot have the same SkinID for the same control type with the same value. A compile error is generated if this occurs.

Creating Multiple Skins

Multiple skins can be supplied in one of two ways. The first method is to supply all of the skins within the same file. For example, to provide a default skin plus a red skin, the skin file could contain these lines:

 <asp:Label runat="server"     ForeColor="#000000" BackColor="#FFFFFF" /> <asp:Label runat="server" SkinID="Red"     ForeColor="#FFFFFF" BackColor="#660000" /> 

Here you just add all of the controls and create duplicates for those that require multiple skins, setting the SkinID for each duplicate to a different name.

The second method is to split the skins into separate files. For example, consider the provision of a Basic theme, with default controls, and two skins Red and Blue . We could use the structure shown in Figure 7.8.

Figure 7.8. Multiple skin files

graphics/07fig08.gif

In this example there is a skin file for each distinct skin. This method is easier to maintain because the skins are completely separate from each other, and it allows more skins to be created by simply copying an existing file and modifying it.

A theme directory can contain other resources, which can be accessed from skin files with relative paths. For example, Figure 7.8 shows an Images directory, allowing skin files to include specific images. This is especially useful for the TreeView control; separate images can be used per theme. For example, consider the following fragment:

 <%@ Page Theme="Basic" %> <asp:TreeView SkinID="Basic"     LeafNodeImage="images\MyTheme_Skin_LeafNode.gif" ... 

In this example the LeafNodeImage property identifies the image to use for leaf nodes of the TreeView . Since this control is skinned , the images are taken from the Images directory under the theme.

Using Stylesheets in Themes

Skin files can also contain stylesheets, allowing a greater separation of styling features. A server-side stylesheet is used for this feature, as shown below:

 <asp:StyleSheetInclude runat="server">   <asp:StyleSheetItem href="Basic.css" /> </asp:StyleSheetInclude> 

For this to work, the ASP.NET page must have a server-based head tag:

 <head runat="server" /> 

This is required because the stylesheet is injected into the head tag at compile time.

Setting a Page Theme

To use a theme on a page, you simply set the Theme property of the page. This can be done either declaratively as an attribute of the Page directive:

 <%@ Page Theme="Basic" %> 

or within code:

 Page.Theme = Request.QueryString("Theme") Page.Theme = Profile.Theme 

When setting the theme programmatically, it must be set within the new page-level PreInit event. For example:

 Sub Page_PreInit(Sender As Object, E As EventArgs)   Page.Theme = Profile.Theme End Sub 

This event must be used because the theme and skin details for controls need to be set before the controls are added to the page, and other events (such as Init , PreRender , Load , and so on) occur too late in the control creation chain.

Setting a Skin

Skins apply to controls, so the SkinID property of the controls must be set. Like the page theme, this can be set either declaratively:

 <asp:Label SkinID="Red" Text="I'm Skinned" /> 

or programmatically:

 Label.SkinID = "Red" Label.SkinID = Profile.SkinID 

The skin applies only to a single control and not child controls. Thus setting the SkinID for a Panel that contains other controls only sets the SkinID for the Panel . If you wish to ensure that all controls on a page have a SkinID applied, you can recurse the Controls collection. For example, Listing 7.16 shows how the page theme and skin could be set for all controls, based on the details set in the user Profile .

Listing 7.16 Setting the Skin for All Controls
 Sub Page_PreInit(Sender As object, E As EventArgs)   Page.Theme = Profile.Theme   SkinControls(Profile.SkinID, Page.Controls) End Sub Private Sub SkinControls(Skin As String, ctls As ControlCollection)   Dim ctl As Control   For Each ctl In ctls     ctl.SkinID = Skin     If ctl.HasControls Then       SkinControls(Skin, ctl.Controls)     End If   Next End Sub 

One problem with this technique is that if a SkinID is not defined for a particular control type in use on the page, an exception is raised. For this reason it's better to explicitly set the skin for individual controls.

Controls dynamically added to a page will have the appropriate theme and skin applied by ASP.NET.

Allowing User Selection of Skins

If your site supports multiple themes and skins, allowing users to select their preferred look is a great feature. It's relatively easy to do dynamically if you stick to a strict convention, keeping individual skins in separate files so you can then simply search for skin files. For example, you could build a theme browser similar to that shown in Figure 7.9, where the themes are shown at the top and some sample controls are shown on the right. Selecting a theme file could then apply that theme.

Figure 7.9. A theme browser

graphics/07fig09.gif

The big problem with this approach is the event ordering. Remember that themes and skins are applied before controls are added to the page, and in this example we set the details in the PreInit event, which is executed before the postback event. This means that when you select the theme or skin, the server-side postback event occurs after the skin details have been set in PreInit . Selecting the same theme or skin again is a workaround as the selected value will already be set from the previous postback and so would be available at the PreInit stage. Another option is to have an Apply button that causes a postback, either to itself or to another page, thus giving you the second postback.

Using Personalization for Themes

Some of the code samples earlier showed the Profile being used to store the theme and skin names . Configuration of this simply requires the properties to be added to the <profile> section in web.config (see Listing 7.17).

Listing 7.17 Configuring Personalization to Store Theme Details
 <configuration>   <system.web>     <personalization>       <profile>         <property name="Theme" />         <property name="SkinID" />       </profile>     </personalization>   <system.web> </configuration> 

Now when storing the selected theme, perhaps from the theme browser shown earlier, you can simply store the user's selected theme in his or her profile when the user selects a particular theme from the appropriate link (see Listing 7.18).

Listing 7.18 Storing the Theme in the Profile
 <asp:LinkButton runat="server" Text="Basic Blue"   onClick="SetTheme" CommandName="BasicBlue" /> <asp:LinkButton runat="server" Text="Smoke and Glass"   onClick="SetThem" CommandName="SmokeAndGlass" /> <script runat="server"> Sub SetTheme(Sender As Object, E As CommandEventArgs)   Profile.Theme = e.CommandName End Sub </script> 

The theme details can then simply be ready from the Profile at any stage, especially during the Page_PreInit event where the theme can be set for the page.

Collections of Controls

Care has to be taken when skinning collections of controls because the themed collection replaces a collection applied in a page. For example, consider the following themed control within MyTheme.skin (see Listing 7.19).

Listing 7.19 A Themed Collection Control
 <asp:RadioButtonList runat="server">   <asp:ListItem value="1">Option 1</asp:ListItem>   <asp:ListItem value="2">Option 2</asp:ListItem>   <asp:ListItem value="3">Option 3</asp:ListItem>   <asp:ListItem value="4">Option 4</asp:ListItem> </asp:RadioButtonList> 

Now consider the page created by Listing 7.20.

Listing 7.20 Using a Themed Collection Control
 <%@ Page Theme="MyTheme" %> <form runat="server">   <asp:RadioButtonList id="list" runat="server">     <asp:ListItem value="5">Option 5</asp:ListItem>     <asp:ListItem value="6">Option 6</asp:ListItem>     <asp:ListItem value="7">Option 7</asp:ListItem>     <asp:ListItem value="8">Option 8</asp:ListItem>   </asp:RadioButtonList> </form> 

The results of running this page are shown in Figure 7.10.

Figure 7.10. A themed collection

graphics/07fig10.gif

Notice that the collection from the theme is used instead of the collection from the page. This is because the controls on the page are replaced by their equivalents in the theme file. To get around this you can change the values in the Page_Load event, either by manually deleting the collection entries and adding them or by data binding, in which case the collection from the theme is replaced.

Disabling Themes

Theming can be explicitly disabled on controls by setting the Enable Theming property to False . When the controls are added to the page, any controls (and their children) with this property set to False will not have the theme applied (see Listing 7.21).

Listing 7.21 Disabling Theming on Controls
 <%@ Page Theme="BasicBlue" %> <asp:Panel runat="server" EnableTheming="False">   <asp:Label id="WelcomeMessage" runat="server" />   <br />   <asp:DataGrid id="News" runat="server" /> </asp:Panel> 

In this case the Panel , the Label , and the DataGrid will not have the theme applied if the EnableTheming property has been set to False . This is particularly useful when including third-party controls, such as search controls, that must conform to a set look.

Adding Themes to a Site

In addition to setting themes at the page level, you can set them globally by modifying the application configuration file, as shown in Listing 7.22.

Listing 7.22 Configuring a Site-Wide Theme
 <configuration>   <system.web>     <pages theme="BasicBlue" />   </system.web> </configuration> 

Like all page settings, this is overridden when set on individual pages.

Enabling Themes in Custom Controls

When building custom controls, theme support is automatically enabled if your control inherits from System.Web.UI.Control (either directly or indirectly). To disable theme support in your control, you can override the EnableTheming property, as shown in Listing 7.23.

Listing 7.23 Disabling Theming in a Custom Control with Properties
 Public Class MyControl     Inherits System.Web.UI.Control   Public Overrides Property EnableTheming() As Boolean     Get       Return False     End Get     Set(ByVal Value As Boolean)       base.EnableTheming = Value     End Set   End Property End Class 

This property can also be set as an attribute on the entire class, to disable theme support for the control (see Listing 7.24).

Listing 7.24 Disabling Theming in a Custom Control with Attributes
 <EnableTheming(False)> _ Public Class MyControl     Inherits System.Web.UI.Control End Class 

Individual properties can also have theme support disabled by use of an attribute (see Listing 7.25).

Listing 7.25 Disabling Theming on a Property
 Public Class MyControl     Inherits System.Web.UI.Control   Private _searchString As String   <Themable(False)> _   Public Property SearchString() As String     Get       Return _searchString     End Get     Set(ByVal Value As Boolean)       _searchString = Value     End Set   End Property End Class 


A First Look at ASP. NET v. 2.0 2003
A First Look at ASP. NET v. 2.0 2003
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 90

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net