February 11, 2012

Applying a theme programatically in ASP.NET Web Forms

I recently responded to a question on Stack Overflow about how to apply a theme programatically in asp.net web forms.

To demonstrate the concept I created a sample application that I’ll discuss in this post.

Setting the theme programatically

Setting the Page theme programatically is fairly trivial. Since it’s not possible to set the theme via a master (layout) page, we need to create a base page that all our site pages inherit from.

public abstract class ThemePage : System.Web.UI.Page
{

}

When creating a new page you then inherit from ThemePage instead of System.Web.UI.Page:

public partial class About : ThemePage
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
}

We set the theme in our base page’s PreInit event. This must be done before calling base.OnPreInit:

public abstract class ThemePage : System.Web.UI.Page
{
    protected override void OnPreInit(EventArgs e)
    {
        this.Theme = "SomeTheme";        
        base.OnPreInit(e);
    }
}

Of course, hard coding the theme is not very useful. You’ll want to allow the user to change the theme from the web application.

Switching themes

In the sample application the work of getting/setting the current theme and listing themes is performed by the ThemeSwitcher utility class:

using System.IO;
using System.Linq;
using System.Web;

namespace WebFormsThemeSwitcher.Application
{
    public class ThemeSwitcher
    {
        private const string ThemeSessionKey = "theme";

        public static string GetCurrentTheme()
        {
            var theme = HttpContext.Current.Session[ThemeSessionKey]
                as string;

            return theme ?? "Default";
        }

        public static void SaveCurrentTheme(string theme)
        {
            HttpContext.Current.Session[ThemeSessionKey] = theme;
        }

        public static string[] ListThemes()
        {
            return (from d in Directory.GetDirectories(HttpContext.Current.Server.MapPath("~/app_themes"))
                    select Path.GetFileName(d)).ToArray();
        }
    }
}

Here we are storing the current theme in Session. In production you would probably want to use a more persistant storage mechanism such as a database or a file.

The ThemeSwitcher class has three methods:

  1. GetCurrentTheme - Looks for the current theme name in Session. If it does not exist it returns the name of our default theme (in this case “Default”).
  2. SaveCurrentTheme - As the name suggests, this saves the current theme into Session.
  3. ListThemes - This method enumerates the theme directories located in “App_Themes”, giving us a list of available themes.

Theme Switcher Control

To switch the theme from within our web application we created a user control (/controls/ThemeSwitcher.ascx) that is added to the top of our master page:

Theme Switcher

The Theme Switcher Control makes use of ThemeSwitcher utility class to populate its dropdown list with the available themes (selecting the current one). When the selection changes, we update the current theme and redirect to the current page:

public partial class ThemeSwitcherControl : System.Web.UI.UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            BindData();
        }
    }

    private void BindData()
    {
        var currentTheme = ThemeSwitcher.GetCurrentTheme();

        foreach (var theme in ThemeSwitcher.ListThemes())
        {
            var item = new ListItem(theme);
            item.Selected = theme == currentTheme;
            ddlThemes.Items.Add(item);
        }
    }

    protected void ddlThemes_SelectedIndexChanged(object sender, EventArgs e)
    {
        ThemeSwitcher.SaveCurrentTheme(ddlThemes.SelectedItem.Value);
        Response.Redirect(Request.RawUrl);
    }       
}

You can download the source here.

© 2022 Ben Foster