tags:

views:

545

answers:

4

I am trying to find a solution (that does not use javascript) to this problem:

I have a master page that includes a navigation menu. Each item in that menu is an action.

When the user selects that action and goes to that view I want to highlight that item in the nav menu to indicate to the user what they are currently viewing.

I could add an action name to a base view model (deriving all my other view models off that) but wonder if there is a nicer way.

(I can already see that a couple of complexities creep in when this is MVC. For a given action any number of different views could be returned, so all of those views would need to highlight the same action in the nav menu. OK).

Thoughts?

P.S. I just noticed that stackoverflow does something similar with the orange highlight on the menu above. I see they are marking with the class "youarehere". What approach did they take I wonder...

+2  A: 

You can use CSS to achieve this.
If you know the ID of the item that you want to highlight, add a CSS rule to your view..

#MenuId
{
color: ...;
etc...
}

To clarify:
Add a placeholder in the head of your Master Page, and then add a style section dynamically in your view...

In the master page:

<head id="Head1" runat="server">   
<asp:ContentPlaceHolder ID="head" runat="server">

</asp:ContentPlaceHolder>
</head>

In the View

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<style type="text/css">
  #<%= Model.IdToHighlight %>
  {
      color:Blue;//or something
  }
</style>
</asp:Content>
markt
Yes I realise the effect will be done with CSS. The problem is I need to set a class in the masterpage, depending on what action is set. Looking for a elegant way...
Schneider
Why does it have to be in the masterpage ? Add a placeholder to your master page and fill it in in the view dynamically. This is not elegant?
markt
Your clarification made me realise that you're effectively suggesting the same thing I did (minutes later). +1
Matt Hamilton
I will try that thanks. I do wonder how useful master pages are when you have partial views...
Schneider
Added a bit more info to clarify..
markt
Notice that stackoverflow uses a flag as opposed to style override for an ID. In fact the lis in the stackoverflow menu are without ids.
Schneider
+1  A: 

When the user selects that action and goes to that view I want to highlight that item in the nav menu to indicate to the user what they are currently viewing.

You could generate your menu with an html helper method, and when you are generating it you could add a class to the menu item relative to the current action.

It can be done with a parameter, or using some of the ways described here.

But I think the most efficient way to do this is with javascript, and the second best option you have is as markt wrote.

eKek0
What do people think about having the nav menu defined in the view instead of in the masterpage? I think it would be OK but seems to violate the DRY principle - something common to all pages should go in masterpage no? Otherwise masterpage becomes "anemic"
Schneider
That's true! Maybe DRY is unknown to many?...
eKek0
You could create a user control and use RenderPartial within your view.. At least then your menu code would be in one place and could render differently depending on the view. But, I'm more in favour of keeping it in the master page unless you really need to generate dynamically..
markt
BTW - that would allow you to generate html in the same way as StackOverflow - you could add a 'youarehere' class to the menu based on the model..
markt
+1  A: 

I'd suggest you go get "Orange tabs" template from mvc design gallery and check it out.

Alexander Taran
To save the world some time Orange Tabs -> http://www.asp.net/mvc/gallery/view.aspx?itemid=77
Schneider
+3  A: 

What I did was this: I created my own helper called RenderMenuLink, so instead of invoking

<li><%= Html.ActionLink("Home", "index", "home")%></li>

I invoke

<%= Html.RenderMenuLink("Home", "index", "home")%>

which in turns adds a link, and in case the user is visiting this link[1] the "selected" class is appended to a "class" attribute of the list item.

[1]: I achieve this functionality by chekcing whether the URL the user is on matches the URL produced by this link. The code is pasted below:


 public static class HtmlMenu
 {
  public static string RenderMenuLink(this HtmlHelper html, string title, string action, string controller)
  {
   UrlHelper url = new UrlHelper(html.ViewContext.RequestContext);
   string link = url.Action(action, controller);
   if(String.IsNullOrEmpty(link))
   {
    throw new ArgumentException("No appropriate route found!");
   }

   var cssClass = String.Empty;
   var uriPath = html.ViewContext.RequestContext.HttpContext.Request.Url.AbsolutePath;
   if((link != "/" && uriPath.StartsWith(link)) || (uriPath == link))
   {
    cssClass = "selected";
   } 
   return String.Format("<li class=\"{0}\"><a href=\"{1}\">{2}</a></li>", cssClass, link, title);
  }
 }
miha