2

In a previous post I had trouble setting the styles on my views in the same way that they do it on the telerik demo site by selecting the style from a dropdown. This was answered however I now have a new but related problem.

I have multiple pages on my site (as is common to MVC) and each of these pages have many telerik controls on them. Allowing the user to style the site using predefined css done for me is great and saves me a lot of work.

The problem is that when I move from page to page, the combo box that telerik uses resets to its default value, thus resetting the styles on the site everytime the user changes a pages (not ideal).

I have tried using sessions to store the state, but there is no way to detect postback like with standard aspx development. So I cant do something like:

if(isPostBack)
{
    if(string.isNullOrEmpty(Session["MyTheme"]+""))
    {
        Session["MyTheme"]="black";
    }
    else
    {
        Session["myTheme"]=//Some combo box selected value
    }
}

Even if I could, the combo box onChange event is handled via JavaScript but the Telerik control requires C# Razor and try as I mgiht, I cant get them to talk and share a simple value.

Ultimately all I want to do, is allow the user pick a theme from the combo box and from then on, that theme is remembered throughout the site until they next change it.

I have tried query strings and sessions, but neither work as I cant access them in JavaScript. Aparently they are used on the server side only.

I have tried cookies but that doesnt work because I cant access them in C# Razor. Aparently they are client side only.

Below is my code:

<head>
@(
  Html.Telerik().StyleSheetRegistrar()
                .DefaultGroup(group => group
                .Add("telerik.common.css")
                .Add(string.IsNullOrEmpty(@Html.ViewContext.HttpContext.Request.QueryString["theme"]) ? "telerik.black.css" : "telerik."+@Html.ViewContext.HttpContext.Request.QueryString["theme"]+".css").Combined(true).Compress(true)
                ))
</head>


<body>
                    @(
                        /* TELERIK COMBOBOX */

                        Html.Telerik().ComboBox()
                        .Name("cbxTheme")
                        .SelectedIndex(0)
                        .ClientEvents(events => events.OnChange("cbxTheme_onChange"))
                        //.BindTo((IEnumerable<DropDownItem>)ViewData["Files"])
                        .Items(item =>
                            {
                                item.Add().Text("black");
                                item.Add().Text("common");
                                item.Add().Text("default");
                                item.Add().Text("forest");
                                item.Add().Text("hay");
                                item.Add().Text("metro");
                                item.Add().Text("office2007");
                                item.Add().Text("office2010black");
                                item.Add().Text("office2010blue");
                                item.Add().Text("office2010silver");
                                item.Add().Text("outlook");
                                item.Add().Text("rtl");
                                item.Add().Text("simple");
                                item.Add().Text("sitefinity");
                                item.Add().Text("sunset");
                                item.Add().Text("telerik");
                                item.Add().Text("transparent");
                                item.Add().Text("vista");
                                item.Add().Text("web20");
                                item.Add().Text("webblue");
                                item.Add().Text("windows7");
                            })
                    )

@(Html.Telerik().ScriptRegistrar().DefaultGroup(group => group.Combined(true).Compress(true)))

</body>

<script type="text/javascript">
function cbxTheme_onChange()
{
    var selectedItemText = $("#cbxTheme").data("tComboBox").text();
    //var selectedItemValue = $("#cbxTheme").data("tComboBox").value();
    window.location.href = window.location.protocol
                         + '//'
                         + window.location.host
                         + window.location.pathname
                         + '?theme='
                         + selectedItemText;
}
</script>

As I explained, for the most part it works fine. Execpt when I click on a likn to another page. Then everything gets set back to a preset default.

Ideally what I am looking for is a way to do a postback when a new item is selected in the combo box (like in the JavaScript). The style is changed so the whole page needs to be refreshed anyway. This works. But when I move to another page, it resets to a default style. So I need a way to store the selected style either client side or server side (preferred as my pages are loaded this way).

I have read this can be done by using a controller but it is not clear how. I would like the controller method if possible, because I am going to use a controller to load a list of CSS styles dynamically allowing the user to download additional styles and they will be added to the list automatically. So anything along this line would be great.

Community
  • 1
  • 1
Francis Rodgers
  • 4,565
  • 8
  • 46
  • 65

1 Answers1

2

You can create a static class with a static property which will act as a global property.

public static class MyTheme
{
    public static string MyGlobalTheme { get; set; }
}

or you could you the Application class.

Application["MyTheme"] = "black";

You could put this code in _Layout.cshtml. If your project name is TProj and your static class is in a folder called Objects, it would look like this.

_Layout.cshtml

@{
  if (@Html.ViewContext.HttpContext.Request.QueryString["theme"] != null)
  {
    TProj.Objects.MyTheme.MyGlobalTheme = Html.ViewContext.HttpContext.Request.QueryString["theme"];
  }
  else
  {
    if (TProj.Objects.MyTheme.MyGlobalTheme == null)
    {
      TProj.Objects.MyTheme.MyGlobalTheme = "black";
    }
  }
}

Now in after this in _Layout.cshtml, you can use the string @TreasuryReportsMvc.Objects.MyTheme.MyGlobalTheme, which should stay the same even when you go to another page. _Layout.cshtml may not be the best place for this logic. You should think about where it makes the most sense for your project.

Be aware that global variables are frowned on by many. This question has a good discussion of Asp.Net MVC global variables.

Community
  • 1
  • 1
Daniel
  • 5,602
  • 4
  • 33
  • 36
  • I dont mean to sound silly, and thanks for the answer. But where do I put the code. I get errors if I put it in the layout.cshtml and other errors if I put it in a base controller, and yet again more errors if I put it into another controller. – Francis Rodgers Jun 28 '12 at 19:08
  • 1
    I updated the answer to try to make it clearer how to use it. – Daniel Jun 28 '12 at 19:57
  • No, problem. I don't care if you don't accept the answer, but I am trying to be helpful. This is working for me. If you explain how it is not working, I can try to help. – Daniel Jun 29 '12 at 14:21
  • When I use the line - ( Application["MyTheme"] = "black"; ) - I get an error asking to include a namespace which shows as: - (using System.Net.Mime.MediaTypeNames.Application) - directly in front of the word application. When I take it out and put it in a using, I get the same error again. I dont know why. I tired this approach because the other code didnt work either. At least now it doesnt give errors though. So thanks for trying anyway. – Francis Rodgers Jun 29 '12 at 14:24
  • I am assuming it is the wrong namespace on the basis that even with the identifier there exectly as you have it, it tells me that I need an identifier (identifier expected). – Francis Rodgers Jun 29 '12 at 14:30
  • 1
    In the example above TProj is the name of my project. You should replace that with the name of your project. Objects is a folder I created where I put the class "MyTheme". _Layout.cshtml needs to know where your class is, but it will be different on your machine. – Daniel Jun 29 '12 at 14:34
  • I intend to add additional functionality later. So I put it in the controllers folder as a class in my base controller. After that I put the code as you suggested in the Layout. I dont get any code errors, however, the telerik control ceases to render properly and it doesnt work anymore. Even after I type something it. Thanks for trying. Im sure its something I am doing, so I will keep hammering away at it. – Francis Rodgers Jun 29 '12 at 14:40
  • By the way if you use Application, the full path should be Html.ViewContext.HttpContext.Application not System.Net.Mime.MediaTypeNames.Application. – Daniel Jun 29 '12 at 14:43
  • I was looking at the article you linked to and would prefer not to use Application[???]=??? if possible. But I will try it just to see if I can get the app to work. – Francis Rodgers Jun 29 '12 at 15:12
  • I agree, it would be better to use the other method. – Daniel Jun 29 '12 at 15:20
  • 1
    Thanks again for your help daniel. I got it working. Silly me was using a wrong string. I used the string out of the combo box and query string instead of doing "telerik" + my query string + ".css". – Francis Rodgers Jul 02 '12 at 08:34