35 votes

Ajout de balises "actives" à la liste de navigation dans une page maître asp.net mvc

Par défaut asp.net projet mvc, dans le Site.Maître de fichier, il y a un menu de navigation de la liste:

<div id="menucontainer">
    <ul id="menu">              
        <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>

Cela rend le navigateur:

<div id="menucontainer"> 
    <ul id="menu">              
        <li><a href="http://stackoverflow.com/">Home</a></li> 
        <li><a href="http://stackoverflow.com/Home/About">About Us</a></li> 
    </ul> 
</div>

Je veux être en mesure de définir dynamiquement la liste active élément, en fonction de la vue qui est appelée. C'est, lorsque l'utilisateur est à la recherche à la page d'accueil, je voudrais le code HTML suivant pour la création:

<div id="menucontainer"> 
    <ul id="menu">              
        <li class="active"><a href="http://stackoverflow.com/">Home</a></li> 
        <li><a href="http://stackoverflow.com/Home/About">About Us</a></li> 
    </ul> 
</div>

Je m'attends à ce que la façon de le faire serait quelque chose comme:

<div id="menucontainer">
    <ul id="menu">              
        <li <% if(actionName == "Index"){%> class="active"<%}%>><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li <% if(actionName == "About"){%> class="active"<%}%>><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>

Le plus important ici est l' <% if(actionName == "Index"){%> class="active"<%}%> ligne de. Je ne sais pas comment faire pour déterminer ce que le courant actionName est.

Toutes les suggestions sur la façon de faire cela? Ou, si je suis sur la mauvaise voie, est-il une meilleure façon de le faire?

37voto

Adam Carr Points 1858

Je me suis fait une méthode d'assistance pour gérer ce genre de chose. Dans le code derrière ma page maître (pourrait être poussé vers une méthode d'extension ... probablement une meilleure approche), j'ai mis le code suivant.

 protected string ActiveActionLinkHelper(string linkText, string actionName, string controlName, string activeClassName)
{
    if (ViewContext.RouteData.Values["action"].ToString() == actionName && 
            ViewContext.RouteData.Values["controller"].ToString() == controlName)
        return Html.ActionLink(linkText, actionName, controlName, new { Class = activeClassName });

    return Html.ActionLink(linkText, actionName, controlName);
}
 

Ensuite, je l'appelle simplement dans ma page comme suit:

 <%= ActiveActionLinkHelper("Home", "Index", "Home", "selected")%>
 

10voto

Craig Stuntz Points 95965

Dans une vue, vous pouvez obtenir le nom de l'action en cours avec:

 ViewContext.RouteData.Values["action"].ToString()
 

10voto

labilbe Points 1231

Vous pouvez également essayer de détecter l’onglet sélectionné en cours à partir du nom de son contrôleur et du nom de la vue, puis ajouter l’attribut de classe.

 public static string MenuActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
    var htmlAttributes = new RouteValueDictionary();

    if (helper.ViewContext.Controller.GetType().Name.Equals(controllerName + "Controller", StringComparison.OrdinalIgnoreCase))
    {
        htmlAttributes.Add("class", "current");
    }

    return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), htmlAttributes);
}
 

10voto

Telvin Nguyen Points 1758

Dans MVC 3 Razor View Engine, vous pouvez le faire en tant que:

 @{string ctrName = ViewContext.RouteData.Values["controller"].ToString();}

<div id="menucontainer">
  <ul id="menu"> 
    <li @if(ctrName == "Home"){<text> class="active"</text>}>@ Html.ActionLink("Home",  "Index", "Home")</li>
    <li @if(ctrName == "About"){<text> class="active"</text>}>@ Html.ActionLink("About Us", "About", "Home")</li>
  </ul>
</div>
 

Mon exemple a fonctionné lorsque j'ai deux pages comme: Accueil / À propos et que son contrôleur a le même nom Index, je reçois donc le nom du contrôleur pour différencier l'action. Si vous voulez avoir de l'action, remplacez simplement par ce qui suit:

 @{string ctrName = ViewContext.RouteData.Values["action"].ToString();}
 

6voto

Tim Iles Points 446

Pour contribuer ma propre réponse (testée dans MVC4), j’ai pris quelques meilleurs morceaux des autres réponses, corrigé quelques problèmes et ajouté un assistant pour travailler avec des URL qui ne sont pas nécessairement résolues via Controller & Action (par exemple, si vous le souhaitez. avoir un CMS intégré traitant des liens de page, etc.)

Le code est également compatible avec github: https://gist.github.com/2851684

 /// 
/// adds the active class if the link's action & controller matches current request
/// 
public static MvcHtmlString MenuActionLink(this HtmlHelper htmlHelper,
    string linkText, string actionName, string controllerName,
    object routeValues = null, object htmlAttributes = null,
    string activeClassName = "active")
{
    IDictionary htmlAttributesDictionary =
        HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

    if (((string)htmlHelper.ViewContext.RouteData.Values["controller"])
            .Equals(controllerName, StringComparison.OrdinalIgnoreCase) &&
        ((string)htmlHelper.ViewContext.RouteData.Values["action"])
            .Equals(actionName, StringComparison.OrdinalIgnoreCase))
    {
        // careful in case class already exists
        htmlAttributesDictionary["class"] += " " + activeClassName;
    }

    return htmlHelper.ActionLink(linkText, actionName, controllerName,
                                    new RouteValueDictionary(routeValues),
                                    htmlAttributesDictionary);
}

/// 
/// adds the active class if the link's path matches current request
/// 
public static MvcHtmlString MenuActionLink(this HtmlHelper htmlHelper,
    string linkText, string path, object htmlAttributes = null,
    string activeClassName = "active")
{
    IDictionary htmlAttributesDictionary =
        HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
    if (HttpContext.Current.Request.Path
        .Equals(path, StringComparison.OrdinalIgnoreCase))
    {
        // careful in case class already exists
        htmlAttributesDictionary["class"] += " " + activeClassName;
    }
    var tagBuilder = new TagBuilder("a")
                            {
                                InnerHtml = !string.IsNullOrEmpty(linkText)
                                                ? HttpUtility.HtmlEncode(linkText)
                                                : string.Empty
                            };
    tagBuilder.MergeAttributes(htmlAttributesDictionary);
    tagBuilder.MergeAttribute("href", path);
    return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
} 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X