Cómo agregar una clase “activa” a Html.ActionLink en ASP.NET MVC

Estoy tratando de agregar una clase “activa” a mi barra de navegación bootstrap en MVC, pero lo siguiente no muestra la clase activa cuando se escribe así:

 

Esto resuelve lo que parece una clase formateada correctamente, pero no funciona:

 Home 

En la documentación de Bootstrap, indica que las tags ‘a’ no se deben usar en la barra de navegación, pero lo anterior es la forma correcta de agregar una clase a Html.ActionLink. ¿Hay alguna otra forma (ordenada) en que pueda hacer esto?

En Bootstrap, la clase active debe aplicarse al elemento

  • y no a . Vea el primer ejemplo aquí: http://getbootstrap.com/components/#navbar

    La forma en que manejas tu estilo de interfaz de usuario según lo que está activo o no tiene nada que ver con el asistente de ActionLink ASP.NET MVC. Esta es la solución adecuada para seguir cómo se construyó el marco Bootstrap.

      

    Editar:

    Como lo más probable es que reutilice su menú en varias páginas, sería inteligente tener una forma de aplicar esa clase seleccionada de forma automática en función de la página actual en lugar de copiar el menú varias veces y hacerlo manualmente.

    La manera más fácil es simplemente usar los valores contenidos en ViewContext.RouteData , es decir, los valores de Action y Controller . Podríamos construir sobre lo que tienes actualmente con algo como esto:

      

    No es bonito en el código, pero hará el trabajo y le permitirá extraer su menú en una vista parcial si lo desea. Hay maneras de hacer esto de una manera mucho más limpia, pero como recién estás comenzando, lo dejo así. ¡La mejor de las suertes aprendiendo ASP.NET MVC!


    Edición tardía:

    Parece que esta pregunta está recibiendo un poco de tráfico, así que pensé en utilizar una extensión más elegante usando una extensión HtmlHelper .

    Editar 24/03/2015: Tuve que volver a escribir este método para permitir múltiples acciones y controladores que desencadenan el comportamiento seleccionado, así como el manejo para cuando se llama al método desde una vista parcial de acción infantil, ¡pensé que compartiría la actualización!

     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 de muestra:

      

    Extensión:

     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:

      

    Decidí hacer esto agregando un parámetro de bolsa de vista en asp.net mvc. Aquí lo que he hecho

    Se agregó ViewBag.Current = "Scheduler"; como parámetro en cada página

    En la página de diseño

      

    Esto resolvió mi problema.

    Puede ser un poco tarde Pero espero que esto ayude.

     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" : ""; } } 

    Y el uso de la siguiente manera:

      

    Obtuve una referencia de http://www.codingeverything.com/2014/05/mvcbootstrapactivenavbar.html

    Sé que esta pregunta es antigua, pero me gustaría agregar mi voz aquí. Creo que es una buena idea dejar el conocimiento de si un enlace está activo o no para el controlador de la vista.

    Solo establecería un valor único para cada vista en la acción del controlador. Por ejemplo, si quisiera activar el enlace de la página de inicio, haría algo como esto:

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

    Entonces, en mi opinión, escribiré algo como esto:

     
  • @Html.ActionLink("Home", "Index", "Home", null, new { title = "Go home" })
  • Cuando navega a una página diferente, diga Progtwigs, ViewBag.Home no existe (en cambio ViewBag.Programs lo hace); por lo tanto, no se representa nada, ni siquiera class = “”. Creo que esto es más limpio tanto para la facilidad de mantenimiento y la limpieza. Tiendo a querer siempre dejar la lógica fuera de la vista tanto como pueda.

    Puede intentar esto: en mi caso estoy cargando el menú de la base de datos basado en el acceso basado en roles, escriba el código en cada vista que menú desea activar en función de su vista.

      

    Agregue ‘.ToString’ para mejorar la comparación en ASP.NET MVC

      

    es posible con una función lambda

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

    entonces el uso

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

    Esta solución es simple para Asp.net MCV 5.

    1. Crea una clase estática, por ejemplo, Utilitarios.cs .

    2. Dentro de la clase crea un 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. llamar así

        

    la respuesta de @dombenoit funciona. Aunque introduce algún código para mantener. Compruebe 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 el uso del método .SetLinksActiveByControllerAndAction() .

    Si se pregunta qué hace posible esta syntax, consulte TwitterBootstrapMVC

    Modifiqué la respuesta “no bonita” de dom y la hice más fea. A veces, dos controladores tienen los nombres de acciones en conflicto (es decir, índice), así que hago esto:

      

    Me di cuenta de que este problema era un problema común para algunos de nosotros, así que publiqué mi propia solución usando el paquete nuget. A continuación puedes ver cómo funciona. Espero que sea útil.

    Nota: Este paquete nuget es mi primer paquete. Entonces, si ve un error, por favor envíe sus comentarios. Gracias.

    1. Instale el paquete o descargue el código fuente y agregue su proyecto

       -Install-Package Betalgo.MvcMenuNavigator 
    2. Agregue sus páginas a una enumeración

       public enum HeaderTop { Dashboard, Product } public enum HeaderSub { Index } 
    3. Pon el filtro en la parte superior de tu Controllor o Acción

       [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. Y úsalo en tu diseño de encabezado como este

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

    Más información: https://github.com/betalgo/MvcMenuNavigator

    si no se muestra, la razón es que necesita dos @ signo:

     @@class 

    PERO, creo que es posible que necesite tener la clase activa en la etiqueta “li”, no en la etiqueta “a”. de acuerdo con los documentos bootstrap ( http://getbootstrap.com/components/#navbar-default ):

      

    por lo tanto, su código será:

      

    También podemos crear UrlHelper partir de RequestContext que podemos obtener de MvcHandler. Por lo tanto, creo que alguien que quiera mantener esta lógica en las plantillas Razor de la siguiente manera sería útil:

    1. En la raíz del proyecto, cree una carpeta llamada AppCode .
    2. Crea un archivo llamado HtmlHelpers.cshtml
    3. Crea un ayudante allí:

       @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. Entonces podemos usar en nuestros puntos de vista de esta manera:

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

    Espero que ayude a alguien.

    También estaba buscando una solución y jQuery ayudó bastante. En primer lugar, debe dar ‘id’ a sus elementos

  • .

     
  • List Guides
  • Después de hacer esto en su página de diseño, puede decirle a jQuery qué elemento

  • debe ser ‘seleccionado’ en su vista.

     @section Scripts{  } 

    Nota: Necesita tener @RenderSection("scripts", required: false) en su página de diseño, justo antes de la etiqueta para agregar esa sección.

    Espero que esto ayude, a continuación se muestra cómo puede ser su menú:

       

    Y agregue debajo de la función auxiliar de MVC debajo de la etiqueta 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; } } 

    Remití la respuesta de http://questionbox.in/add-active-class-menu-link-html-actionlink-asp-net-mvc/

    Me gustaría proponer esta solución que se basa en la primera parte de la respuesta de Dom.

    Primero definimos dos variables, “acción” y “controlador” y las usamos para determinar el enlace activo:

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

    Y entonces:

      

    Ahora se ve mejor y no necesita soluciones más complejas.

    He hecho una combinación de respuestas arriba e hice mi solución.

    Asi que..

    Primero en el bloque de afeitar, cree una variable de cadena que contendrá el valor de nombre del controlador y la acción que el usuario llama.

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

    Luego use una combinación de código HTML y Razor:

       

    Creo que esto es bueno porque no necesita acceder a “ViewContext.RouteData.Values” cada vez para obtener el nombre del controlador y el nombre de la acción.

    Mi solución a este problema es

     
  • About
  • Una forma mejor puede ser agregar un método de extensión Html para devolver la ruta actual para compararla con el enlace

    Teniendo en cuenta lo que publicó Damith, me gusta pensar que simplemente puede calificar activo por el Viewbag.Title (la mejor práctica es rellenar esto en sus páginas de contenido permitiendo que su página _Layout.cshtml contenga sus barras de vínculos). También tenga en cuenta que si está utilizando elementos del submenú también funciona bien:

     
  • Dashboard
  • Creo que aquí hay un código más pequeño y más limpio para hacer que el menú seleccionado sea “activo”:

       

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