2009-09-24 11 views
17

Comme base de discussion. Créez un projet Web ASP.NET MVC standard.Comment faire pour afficher visuellement la page actuelle dans ASP.NET MVC?

Il contiendra deux éléments de menu dans la page principale:

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

Comment puis-je définir le style visuel CSS indiquant la page en cours. Par exemple, lorsque dans la page A propos/contrôleur, je essentiellement comme le faire:

<%= Html.ActionLink("About", "About", "Home", new {class="current"})%></li> 

Et, bien sûr, quand sur la page d'accueil:

<%= Html.ActionLink("Home", "Index", "Home", new {class="current"})%></li> 

(Avoir un style CSS nom courant qui indique visuellement dans le menu que c'est la page actuelle.)

Je pourrais diviser le menu div de la page maîtresse en un espace réservé de contenu, mais cela signifierait que je dois mettre le menu sur chaque page .

Des idées, existe-t-il une bonne solution à cela?

Répondre

24

La meilleure façon est d'obtenir le régulateur de courant et de l'action de RouteData du ViewContext. Notez le changement de signature et l'utilisation de @ pour échapper le mot-clé.

<% var controller = ViewContext.RouteData.Values["controller"] as string ?? "Home"; 
    var action = ViewContext.RouteData.Values["action"] as string ?? "Index"; 
    var page = (controller + ":" + action).ToLower(); 
%> 

<%= Html.ActionLink("About", "About", "Home", null, 
        new { @class = page == "home:about" ? "current" : "") %> 
<%= Html.ActionLink("Home", "Index", "Home", null, 
        new { @class = page == "home:index" ? "current" : "") %> 

Notez que vous pouvez combiner cette extension HtmlHelper comme @ Jon's et la rendre plus propre.

<%= Html.MenuLink("About", "About", "Home", null, null, "current") %> 

Où MenuActionLink est

public static class MenuHelperExtensions 
{ 
    public static string MenuLink(this HtmlHelper helper, 
            string text, 
            string action, 
            string controller, 
            object routeValues, 
            object htmlAttributes, 
            string currentClass) 
    { 
     RouteValueDictionary attributes = new RouteValueDictionary(htmlAttributes); 
     string currentController = helper.ViewContext.RouteData.Values["controller"] as string ?? "home"; 
     string currentAction = helper.ViewContext.RouteData.Values["action"] as string ?? "index"; 
     string page = string.Format("{0}:{1}", currentController, currentAction).ToLower(); 
     string thisPage = string.Format("{0}:{1}", controller, action).ToLower(); 
     attributes["class"] = (page == thisPage) ? currentClass : ""; 
     return helper.ActionLink(text, action, controller, new RouteValueDictionary(routeValues), attributes); 
    } 
} 
+0

Pas une bonne solution. Une vue ne devrait rien savoir des contrôleurs et des actions. Les données à afficher ne doivent être fournies que par le modèle. –

+1

Ce n'est qu'un raccourci pour obtenir l'URL - vous pouvez faire la même chose en utilisant l'URL demandée, mais vous devrez alors l'analyser. Je suis satisfait de ce mécanisme qui ne brise pas le schéma. – tvanfosson

+0

La syntaxe est-elle correcte? Je reçois "Impossible d'appliquer l'indexation avec [] à une expression de type" System.Web.Routing ".RouteData '" –

0

Il se peut que ce soit le 5ème paramètre, placez donc une valeur nulle avant votre attribut html. Ce poste ici décrit comme tel, mais vous pouvez passer des choses au 4ème arguement, le 5 est spécifiquement pour htmlAttributes

+0

@class au lieu de classe :) –

1

J'ai récemment créé un Helper HTML pour ce qui ressemble à:

public static string NavigationLink(this HtmlHelper helper, string path, string text) 
{ 
    string cssClass = String.Empty; 
    if (HttpContext.Current.Request.Path.IndexOf(path) != -1) 
    { 
     cssClass = "class = 'selected'"; 
    } 

    return String.Format(@"<li><a href='{0}' {1}>{2}</a></li>", path, cssClass, text); 
} 

La mise en œuvre se présente comme suit:

<ul id="Navigation"> 
    <%=Html.NavigationLink("/Path1", "Text1")%> 
    <%=Html.NavigationLink("/Path2", "Text2")%> 
    <%=Html.NavigationLink("/Path3", "Text3")%> 
    <%=Html.NavigationLink("/Path4", "Text4")%> 
    </ul> 
+0

J'ai quelques problèmes avec cela. Tout d'abord, il n'aborde pas le casse des chaînes et se cassera si vous fournissez un boîtier différent dans l'URL (souvenez-vous que les utilisateurs peuvent les taper directement). Deuxièmement, il sera difficile de faire un test unitaire compte tenu de la dépendance au static HttpContext.Current. Troisièmement, il se décompose si vous avez plusieurs niveaux d'actions/menus comme le niveau «supérieur» correspondra à tous les sous-niveaux. Certes, ma solution a aussi le troisième problème, mais comme il ne dépend pas de la correspondance de chaînes, il est plus facile de le modifier pour accommoder plusieurs niveaux. – tvanfosson

+0

... J'aime bien, et j'ai emprunté l'idée - merci - l'idée d'en faire une méthode d'extension pour rendre le code de la vue plus propre. – tvanfosson

+0

Merci pour les commentaires! Je suis toujours novice dans tout cela et je cherche toujours des moyens d'améliorer mon code. – Jon

1

Si vous utilisez T4MVC , Vous pouvez utiliser ceci:

 public static HtmlString MenuLink(
     this HtmlHelper helper, 
     string text, 
     IT4MVCActionResult action, 
     object htmlAttributes = null) 
    { 
     var currentController = helper.ViewContext.RouteData.Values["controller"] as string ?? "home"; 
     var currentAction = helper.ViewContext.RouteData.Values["action"] as string ?? "index"; 

     var attributes = new RouteValueDictionary(htmlAttributes); 
     var cssClass = (attributes.ContainsKey("class")) 
          ? attributes["class"] + " " 
          : string.Empty; 

     string selectedClass; 
     if(action.Controller.Equals(currentController, StringComparison.InvariantCultureIgnoreCase) 
     { 
      selectedClass = "selected-parent"; 
      if(action.Action.Equals(currentAction, StringComparison.InvariantCultureIgnoreCase)) 
       selectedClass = "selected"; 
     } 
     cssClass += selectedClass; 

     attributes["class"] = cssClass; 

     return helper.ActionLink(text, (ActionResult)action, attributes); 
    } 
0
<script type="javascript/text"> 
$(document).ready(function() { 

     @if (Request.Url.AbsolutePath.ToLower() == "/") 
     { 
      @Html.Raw("$('.navbar-nav li').eq(0).attr('class','active');") 
     } 

     @if (Request.Url.AbsolutePath.ToLower().Contains("details")) 
     { 
      @Html.Raw("$('.navbar-nav li').eq(1).attr('class','active');") 
     } 

     @if (Request.Url.AbsolutePath.ToLower().Contains("schedule")) 
     { 
      @Html.Raw("$('.navbar-nav li').eq(2).attr('class','active');") 
     } 

    }); 
</script> 

lançai cela ensemble dans 5 minutes, je pourrais probablement factoriser, mais devrait vous donner l'idée de base, il est probablement plus utile pour les sites plus petits.

Questions connexes