Como adicionar class “ativa” ao Html.ActionLink no asp.net MVC

Eu estou tentando adicionar uma class “ativa” ao meu bootstrap navbar no MVC, mas o seguinte não mostra a class ativa quando escrito assim:

 

Isso resolve o que parece ser uma class formatada corretamente, mas não funciona:

 Home 

Na documentação do Bootstrap, ele afirma que as tags ‘a’ não devem ser usadas na barra de navegação, mas o acima é como eu acredito ser a maneira correta de adicionar uma class a um Html.ActionLink. Existe outra maneira (arrumada) de fazer isso?

No Bootstrap, a class active precisa ser aplicada ao elemento

  • e não ao . Veja o primeiro exemplo aqui: http://getbootstrap.com/components/#navbar

    A maneira como você lida com seu estilo de interface do usuário com base no que está ativo ou não tem nada a ver com o ActionLink da ASP.NET MVC. Esta é a solução adequada para seguir como o framework Bootstrap foi construído.

      

    Editar:

    Como você provavelmente estará reutilizando seu menu em várias páginas, seria inteligente ter uma maneira de aplicar essa class selecionada automaticamente com base na página atual, em vez de copiar o menu várias vezes e fazer isso manualmente.

    A maneira mais fácil é simplesmente usar os valores contidos em ViewContext.RouteData , ou seja, os valores Action e Controller . Poderíamos construir o que você tem atualmente com algo assim:

      

    Não é bonito no código, mas vai fazer o trabalho e permitir que você extraia seu menu em uma visão parcial, se quiser. Existem maneiras de fazer isso de uma maneira muito mais limpa, mas como você está apenas começando, deixarei por isso mesmo. Boa sorte aprendendo asp.net MVC!


    Edição tardia:

    Esta questão parece estar recebendo um pouco de tráfego, então pensei em lançar uma solução mais elegante usando uma extensão HtmlHelper .

    Editar 24-03-2015: Teve que rewrite este método para permitir múltiplas ações e controladores triggersndo o comportamento selecionado, bem como manipular quando o método é chamado a partir de uma visão parcial de ação filho, pensei em compartilhar a atualização!

     public static string IsSelected(this HtmlHelper html, string controllers = "", string actions = "", string cssClass = "selected") { ViewContext viewContext = html.ViewContext; bool isChildAction = viewContext.Controller.ControllerContext.IsChildAction; if (isChildAction) viewContext = html.ViewContext.ParentActionViewContext; RouteValueDictionary routeValues = viewContext.RouteData.Values; string currentAction = routeValues["action"].ToString(); string currentController = routeValues["controller"].ToString(); if (String.IsNullOrEmpty(actions)) actions = currentAction; if (String.IsNullOrEmpty(controllers)) controllers = currentController; string[] acceptedActions = actions.Trim().Split(',').Distinct().ToArray(); string[] acceptedControllers = controllers.Trim().Split(',').Distinct().ToArray(); return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ? cssClass : String.Empty; } 

    Uso da amostra:

      

    Extensão:

     public static MvcHtmlString LiActionLink(this HtmlHelper html, string text, string action, string controller) { var context = html.ViewContext; if (context.Controller.ControllerContext.IsChildAction) context = html.ViewContext.ParentActionViewContext; var routeValues = context.RouteData.Values; var currentAction = routeValues["action"].ToString(); var currentController = routeValues["controller"].ToString(); var str = String.Format("
  • {1}
  • ", currentAction.Equals(action, StringComparison.InvariantCulture) && currentController.Equals(controller, StringComparison.InvariantCulture) ? " class=\"active\"" : String.Empty, html.ActionLink(text, action, controller).ToHtmlString() ); return new MvcHtmlString(str); }

    Uso:

      

    Eu consegui fazer isso adicionando um parâmetro view bag no asp.net mvc. Aqui o que eu fiz

    Adicionado ViewBag.Current = "Scheduler"; como parâmetro em cada página

    Na página de layout

      

    Isso resolveu meu problema.

    Pode ser um pouco tarde. Mas espero que isso ajude.

     public static class Utilities { public static string IsActive(this HtmlHelper html, string control, string action) { var routeData = html.ViewContext.RouteData; var routeAction = (string)routeData.Values["action"]; var routeControl = (string)routeData.Values["controller"]; // both must match var returnActive = control == routeControl && action == routeAction; return returnActive ? "active" : ""; } } 

    E o uso da seguinte forma:

      

    Tenho uma referência de http://www.codingeverything.com/2014/05/mvcbootstrapactivenavbar.html

    Eu sei que esta pergunta é antiga, mas vou apenas adicionar minha voz aqui. Eu acredito que é uma boa idéia deixar o conhecimento de se um link está ativo ou não para o controlador da visão.

    Gostaria apenas de definir um valor exclusivo para cada exibição na ação do controlador. Por exemplo, se eu quisesse ativar o link da home page, faria algo assim:

     public ActionResult Index() { ViewBag.Title = "Home"; ViewBag.Home = "class = active"; return View(); } 

    Então, na minha opinião, vou escrever algo assim:

     
  • @Html.ActionLink("Home", "Index", "Home", null, new { title = "Go home" })
  • Quando você navega para uma página diferente, por exemplo, Programas, ViewBag.Home não existe (em vez disso, o ViewBag.Programs); portanto, nada é processado, nem mesmo class = “”. Eu acho que isso é mais limpo tanto para manutenção e limpeza. Eu sempre quis deixar a lógica fora da visão tanto quanto eu posso.

    Você pode tentar isso: No meu caso eu estou carregando o menu do database com base no access baseado em function, Escreva o código em sua cada vista que menu seu quer ativo com base em sua visão.

      

    Adicionar ‘.ToString’ para melhorar a comparação no asp.net MVC

      

    é possível com uma function lambda

     @{ string controllerAction = ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString(); Func IsSelected= x => x==controllerAction ? "active" : ""; } 

    então uso

      @Html.ActionLink("Inicio", "Index", "Home", new { area = "" }, new { @class = IsSelected("HomeIndex")}) 

    Esta solução é simples para o Asp.net MCV 5.

    1. Crie uma class estática, por exemplo, Utilitarios.cs .

    2. Dentro da class, crie um método estático:

       public static string IsLinkActive(this UrlHelper url, string action, string controller) { if (url.RequestContext.RouteData.Values["controller"].ToString() == controller && url.RequestContext.RouteData.Values["action"].ToString() == action) { return "active"; } return ""; } 
    3. ligue assim

        

    a resposta de @dombenoit funciona. Embora introduza algum código para manter. Verifique esta syntax:

     using (var nav = Html.Bootstrap().Begin(new Nav().Style(NavType.NavBar).SetLinksActiveByControllerAndAction())) { @nav.ActionLink("Link 1", "action1") @nav.ActionLink("Link 2", "action2") @nav.Link("External Link", "#") } 

    Observe o uso do método .SetLinksActiveByControllerAndAction() .

    Se você quer saber o que torna essa syntax possível, confira TwitterBootstrapMVC

    Eu modifiquei a resposta “não bonita” de dom e a tornei mais feia. Às vezes, dois controladores têm os nomes de ação conflitantes (isto é, Index), então eu faço isso:

      

    Percebi que esse problema era um problema comum para alguns de nós, então publiquei minha própria solução usando o pacote nuget. Abaixo você pode ver como funciona. Espero que isso seja útil.

    Nota: Este pacote nuget é o meu primeiro pacote. Então, se você perceber um erro, por favor dê um feedback. Obrigado.

    1. Instalar o pacote ou baixar o código fonte e adicionar seu projeto

       -Install-Package Betalgo.MvcMenuNavigator 
    2. Adicione suas páginas a um enum

       public enum HeaderTop { Dashboard, Product } public enum HeaderSub { Index } 
    3. Coloque o filtro no topo do seu Controllor ou Action

       [MenuNavigator(HeaderTop.Product, HeaderSub.Index)] public class ProductsController : Controller { public async Task Index() { return View(); } [MenuNavigator(HeaderTop.Dashboard, HeaderSub.Index)] public async Task Dashboard() { return View(); } } 
    4. E usá-lo em seu layout de header como este

       @{ var headerTop = (HeaderTop?)MenuNavigatorPageDataNavigatorPageData.HeaderTop; var headerSub = (HeaderSub?)MenuNavigatorPageDataNavigatorPageData.HeaderSub; }  

    Mais informações: https://github.com/betalgo/MvcMenuNavigator

    se é que não está mostrando nada, a razão é que você precisa de dois sinais @:

     @@class 

    MAS, acredito que você talvez precise ter a class ativa na tag “li” não na tag “a”. de acordo com a documentação do bootstrap ( http://getbootstrap.com/components/#navbar-default ):

      

    portanto, seu código será:

      

    Nós também podemos criar o UrlHelper partir do RequestContext que podemos obter do próprio MvcHandler. Portanto, acredito que alguém que queira manter essa lógica nos modelos do Razor, seguindo o seguinte caminho, seria útil:

    1. No projeto root crie uma pasta chamada AppCode .
    2. Crie um arquivo chamado HtmlHelpers.cshtml
    3. Crie um ajudante lá:

       @helper MenuItem(string action, string controller) { var mvcHandler = Context.CurrentHandler as MvcHandler; if (mvcHandler != null) { var url = new UrlHelper(mvcHandler.RequestContext); var routeData = mvcHandler.RequestContext.RouteData; var currentAction = routeData.Values["action"].ToString(); var currentController = routeData.Values["controller"].ToString(); var isCurrent = string.Equals(currentAction, action, StringComparison.InvariantCultureIgnoreCase) && string.Equals(currentController, controller, StringComparison.InvariantCultureIgnoreCase); 
      @url.Action(action, controller)
      } }
    4. Então podemos usar em nossos pontos de vista como este:

       @HtmlHelpers.MenuItem("Default", "Home") 

    Espero que isso ajude a alguém.

    Eu também estava procurando uma solução e jQuery ajudou muito. Primeiro, você precisa dar ‘id’s aos seus elementos

  • .

     
  • List Guides
  • Depois de fazer isso na sua página de layout, você pode dizer ao jQuery qual

  • elemento deve ser ‘selecionado’ na sua visualização.

     @section Scripts{  } 

    Nota: Você precisa ter @RenderSection("scripts", required: false) na sua página de layout, logo antes da tag para adicionar essa seção.

    Espero que isso ajude, abaixo é como o seu menu pode ser:

       

    E adicione abaixo a function auxiliar MVC abaixo da tag html.

      @helper IsMenuSelected(string actionName, string controllerName, string className) { var conname = ViewContext.RouteData.Values["controller"].ToString().ToLower(); var actname = ViewContext.RouteData.Values["action"].ToString().ToLower(); if (conname == controllerName.ToLower() && actname == actionName.ToLower()) { @className; } } 

    Eu me referi a resposta de http://questionbox.in/add-active-class-menu-link-html-actionlink-asp-net-mvc/

    Eu gostaria de propor esta solução que é baseada na primeira parte da resposta de Dom.

    Primeiro definimos duas variables, “action” e “controller” e as usamos para determinar o link ativo:

     { string controller = ViewContext.RouteData.Values["Controller"].ToString(); string action = ViewContext.RouteData.Values["Action"].ToString();} 

    E depois:

      

    Agora parece melhor e não há necessidade de soluções mais complexas.

    Eu fiz combinação de respostas acima e fiz a minha solução.

    Assim..

    Primeiro no bloco de razor, crie uma variável de cadeia que conterá o valor do nome do controlador e da ação que é chamada pelo usuário.

      @{ string controllerAction = ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString(); } 

    Em seguida, use a combinação de código HTML e Razor:

       

    Eu acho que isso é bom porque você não precisa acessar “ViewContext.RouteData.Values” cada vez para obter o nome do controlador e o nome da ação.

    Minha solução para este problema é

     
  • About
  • Uma maneira melhor pode ser adicionar um método de extensão Html para retornar o caminho atual a ser comparado com o link

    Considerando o que Damith postou, eu gosto de pensar que você pode apenas se qualificar ativo pelo Viewbag.Title (a melhor prática é preencher isso em suas páginas de conteúdo, permitindo que sua página de _Layout.cshtml segure suas barras de links). Observe também que, se você estiver usando itens de submenu , também funciona bem:

     
  • Dashboard
  • Eu acredito que aqui é um código mais limpo e pequeno para fazer o menu selecionado estar “ativo”:

       

      public static string IfSelected(this HtmlHelper html, string action) { return html .ViewContext .RouteData .Values["action"] .ToString() == action ? " active" : ""; }