views:

301

answers:

2

In my master page I have a top-level menu that is created using ActionLinks:

<ul id="topNav">
  <li><%=Html.ActionLink("Home", "Index", "Home")%></li>
  <li><%=Html.ActionLink("News", "Index", "News")%></li>
  <li><%=Html.ActionLink("Projects", "Index", "Projects")%></li>
  <li><%=Html.ActionLink("About", "About", "Home")%></li>
  <li><%=Html.ActionLink("Contact", "Contact", "Home")%></li>
  <li><%=Html.ActionLink("Photos", "Photos", "Photos")%></li>
</ul> 

I want to dynamically add a class named "current" to the link that the site is currently pointing to. So, for example, when the site is sitting at the home page, the menu link would render like this:

<li><a class="current" href="/">Home</a></li>

Do I have to overload the ActionLink method to do this, or create an entirely new HtmlHelper, or is there a better way?

I'm fairly new to MVC, so I'm not sure what is the correct way to go about this.

Thanks in advance.

+2  A: 

You could write your own extension method for this (sorry for my VB which is a little rusty):

<Extension> _
Public Shared Function MyActionLink( _
    ByVal htmlHelper As HtmlHelper, _ 
    ByVal linkText As String, _ 
    ByVal actionName As String, _ 
    ByVal controllerName As String) As MvcHtmlString

    Dim currentAction As String = TryCast(htmlHelper.ViewContext.RouteData.Values.Item("action"), String)
    Dim currentController As String = TryCast(htmlHelper.ViewContext.RouteData.Values.Item("controller"), String)
    If ((actionName = currentAction) AndAlso _
        (controllerName = currentController)) _ 
    Then
        Return htmlHelper.ActionLink( _
            linkText, _
            actionName, _
            controllerName, _ 
            Nothing, _
            New { _
                .class = "current" _
            })
    End If
    Return htmlHelper.ActionLink(linkText, actionName, controllerName)
End Function

which you could use like so:

<ul id="topNav">
  <li><%=Html.MyActionLink("Home", "Index", "Home")%></li>
  <li><%=Html.MyActionLink("News", "Index", "News")%></li>
  <li><%=Html.MyActionLink("Projects", "Index", "Projects")%></li>
  <li><%=Html.MyActionLink("About", "About", "Home")%></li>
  <li><%=Html.MyActionLink("Contact", "Contact", "Home")%></li>
  <li><%=Html.MyActionLink("Photos", "Photos", "Photos")%></li>
</ul> 
Darin Dimitrov
This worked perfectly! I only had to make one modification to your code sample: the syntax for the htmlAttributes object is New With { .class="current" }Thanks!
camainc
I'm glad you made this work. As I said my VB.NET is rusty :-)
Darin Dimitrov
Not bad for being rusty!
camainc
+1, much better than my solution, which I will be replacing with your method when I get to it.
37Stars
A: 

From the sounds of it you may want something like this.

Create a default constructor for each controller and set a value in ViewData.

public HomeController()
    : base()
{
    ViewData["selected"] = "home";
}

Then in your Site.Master file you can do this:

<li class="<%= ((ViewData["selected"] == "home") ? "current" : "") %>"><%= Html.ActionLink("Home", "Index", "Home") %></li>

It could be cleaned up a bit, but you get the idea.

37Stars