• Post Calendar

    May 2015
    S M T W T F S
    « Apr   Jun »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  

Dynamically Load Bootswatch Themes

This post shows how I dynamically load a user’s selected theme in an MVC 5 application that’s using Bootstrap and Bootswatch.

App_Themes Folder

I didn’t use use that… So you can skip this section if you like.

In the past, different themes were placed in different folders and you could just enumerate the subdirectories in ~/App_Themes. But Bootswatch doesn’t use that.

Bootswatch Install Location

Bootswatch places two files in your ~/Content folder: 1) bootstrap.<theme name>.css, and 2) bootstrap.<theme name>.min.css.

Available Themes Code

So I just search that directory and look for all the files matching the “bootstrap.*.min.css” pattern and let the user select the one they want.

AvailableThemes
  1. /// <summary>
  2. /// Helps find available themes so the user can choose one. Alwo helps
  3. /// find the selected theme for loading dynamically.
  4. /// </summary>
  5. public static class AvailableThemes
  6. {
  7.     public const string ContentDirectory = "Content";
  8.     internal static ICollection<string> GetThemesList(HttpRequestBase request)
  9.     {
  10.         return GetThemesList(request.PhysicalApplicationPath);
  11.     }
  12.  
  13.     public static ICollection<string> GetThemesList(string physicalApplicationPath)
  14.     {
  15.         var themes = new Collection<string>();
  16.         var dir = Path.Combine(physicalApplicationPath, ContentDirectory);
  17.         var dirInfo = new DirectoryInfo(dir);
  18.         foreach (var themeFile in dirInfo.GetFiles("bootstrap.*.min.css", SearchOption.TopDirectoryOnly))
  19.         {
  20.             var parts = themeFile.Name.Split(new[] { '.' });
  21.             // Based on our filter search pattern we know we'll have at least 2 parts.
  22.             var themeTitle = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(parts[1]);
  23.             themes.Add(themeTitle);
  24.         }
  25.         return themes;
  26.     }
  27.  
  28.     public static string GetThemeFile(string themeName)
  29.     {
  30.         return "/" + ContentDirectory + "/bootstrap." + themeName + ".min.css";
  31.     }
  32.  
  33.  
  34.     public static string GetValidTheme(HttpRequestBase request, string savedThemeName)
  35.     {
  36.         return GetValidTheme(request.PhysicalApplicationPath, savedThemeName);
  37.     }
  38.  
  39.     /// <summary>
  40.     /// If the user's saved theme name is still available use it. If they are using
  41.     /// a theme that has sense been uninstalled, then just have them use the first
  42.     /// available theme.
  43.     /// </summary>
  44.     /// <param name="physicalApplicationPath">The physical directory location.</param>
  45.     /// <param name="savedThemeName">The name of the theme the user has chosen.</param>
  46.     /// <returns>A valid theme name.</returns>
  47.     public static string GetValidTheme(string physicalApplicationPath, string savedThemeName)
  48.     {
  49.         var themes = GetThemesList(physicalApplicationPath).Select(t => t.ToLowerInvariant());
  50.         if (themes.Contains(savedThemeName.ToLowerInvariant()))
  51.             return savedThemeName.ToLowerInvariant();
  52.         return themes.First();
  53.     }
  54. }

Then the Razor File

This is the code from the Views/Shared/_Layout.cshtml file (toward the top). So 3 lines of code allowing us to have the right bootstrap.*.min.cs filename to load.

_Layout.cshtml
  1. @{
  2.     ViewBag.Title = "Google Maps Filter";
  3.     //Layout = null;
  4.     // Get the user's saved theme.
  5.     var savedThemeName = SettingsController.GetTheme(Request);
  6.     // Validate the theme. If it no longer is available, then return the first available theme.
  7.     var themeName = AvailableThemes.GetValidTheme(Request, savedThemeName);
  8.     // Now get the actual file to load using Syles.Render.
  9.     var boostrapThemeCss = AvailableThemes.GetThemeFile(themeName);
  10. }
  11. <!DOCTYPE html>
  12. <html>
  13. <head>
  14.     @*Load the user's selected theme*@
  15.     @Styles.Render(boostrapThemeCss)

 

Summary

It’s it quite easy to dynamically load the Bootswatch Bootstrap themes using well tested C# and Razor syntax rather than javascript as I’ve seen in so many places. This keeps your code much cleaner. And again, if you add new themes, you can find them easily to present to your user. Using the NuGet install you would just add one, then you don’t need to change a single line of code for everything to work. Again, the same is true if you uninstall an existing theme.

1 Comment  »

RSS feed for comments on this post, TrackBack URI

Leave a Comment