Reputation: 465
I would like to change the CSS files on the fly (dynamically). I am developing in MVC 4 using Razor views. At the moment they are pulled from the web.config...
My bundle registration
bundles.Add(New StyleBundle("~/Content/themes/" + Domain.GetTheme + "/css").Include(
"~/Content/themes/" + Domain.GetTheme + "/Main.css",
"~/Content/themes/" + Domain.GetTheme + "/Content.css"))
Razor View
@Styles.Render("~/Content/themes/" + Domain.GetTheme + "/css")
Code in GetTheme property
Public Shared ReadOnly Property GetTheme As String
Get
Return ConfigurationManager.AppSettings("Theme")
End Get
End Property
I'm not sure if this is the best way, but it works.
Research so far...
But now I want to change the theme on the fly. My initial idea was to access a querystring parameter. So if it contained ?Theme=Green then the CSS files would pick up the green version. The querystring value would be stored in session state so that the CSS would continue to use green until changed again via the querystring.
I started off by creating an attibute that I could apply to my controller...
Attribute
Public Class LoadThemeAttribute
Inherits ActionFilterAttribute
Public Overrides Sub OnActionExecuted(filterContext As ActionExecutedContext)
MyBase.OnActionExecuted(filterContext)
If HttpContext.Current.Request.QueryString("Theme") IsNot Nothing Then
HttpContext.Current.Session("Theme") = HttpContext.Current.Request.QueryString("Theme")
End If
End Sub
End Class
Controller
<LoadTheme>
Public Class CompanyController
Inherits System.Web.Mvc.Controller
...
End Class
Then in my _Layout.vbhtml razor view I override the CSS files as follows:-
@If Session("Theme") IsNot Nothing Then
@<link href="/Content/themes/@Session("Theme")/Main.css" rel="stylesheet"/>
@<link href="/Content/themes/@Session("Theme")/Content.css" rel="stylesheet"/>
Else
@Styles.Render("~/Content/themes/" + Domain.GetTheme + "/css")
End If
I couldn't use the Render statement, I am assuming this is because this is called once when the project loads and cannot be called again. I certainly could not get it to work.
So my question is this:- Everything seems to work, but I just want to know if this is a good approach - is it a good MVC way to change the CSS files?
Upvotes: 1
Views: 3149
Reputation: 397
So I've pretty much had the same issue you had. A quick cure I did was remove my theme/css from the bundle and put it separate on my layout.vbhtml /master page. I gave the tag and id property, referenced it an a javascript function and changed the href to the different css I wanted loaded. If this is not enough information let me know, ill detail more.
Updated example from my program. layout.vbhtml header
<head>
<meta charset="utf-8" />
<title>Amtrust - Print Metrics @*@ViewData("Title")*@</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
<link id="theme"
href="~/Content/themes/jquery-blue-theme/css/start/jquery-ui- 1.10.3.custom.css" rel="stylesheet" />
@Styles.Render("~/Content/_Layout")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")
@Scripts.Render("~/Scripts/_Layout")
</head>
site.master.js -> js file I use to keep the theme consistent on all pages.
var domainName;
$(document).ready(function () {
//loading = document.getElementById('loading');
//pagediv = document.getElementById('page');
//alarum = document.getElementById('alarum');
//alarum = $('#alarum');
jQuery's .append() method
$("#menu").menu();
hideLoading();
//Apply UI skins to controls
$(function ()
{
$('#printinvButton').button();
$('#docsearchButton').button();
$('#policysearchButton').button();
$('#metricsButton').button();
$('#themeButton').button();
});
//setInterval(function () { bannerAlert() }, 4000);
if (sessionStorage.getItem('theme') != null) {
$('#theme').attr('href', sessionStorage.getItem('theme'));
}
domainName = location.protocol + '//' + location.host;
});
var counter = 0;
function switchTheme() {
var theme;
var imageRoot = document.body.getAttribute('data-root');
if (counter == 0) {
theme = domainName + '/PrintRoomMetrics/Content/themes/jquery-blackgrey- theme/css/blackGrey/jquery-ui-1.10.3.custom.min.css';
$('#theme').attr('href', theme);
counter++;
}
else if (counter == 1) {
theme =
domainName + '/PrintRoomMetrics/Content/themes/jquery-chrome-theme
/css/overcast/jquery-ui-1.10.3.custom.min.css';
$('#theme').attr('href', theme);
counter++;
}
else if (counter == 2) {
theme = domainName + '/PrintRoomMetrics/Content/themes/jquery-blue-theme/css/start/jquery-ui- 1.10.3.custom.min.css';
$('#theme').attr('href', theme);
counter++;
}
if (counter == 3) {
counter = 0;
}
sessionStorage.setItem('theme', theme);// store data for session
}
hope you can figure out what I did. Ignore my app code and only pay attention to what you need.
Upvotes: 1