ASP.NET MVC에서 Html.ActionLink에“활성”클래스를 추가하는 방법


128

MVC에서 부트 스트랩 탐색 모음에 "active"클래스를 추가하려고하는데 다음과 같이 작성하면 다음과 같이 활성 클래스가 표시되지 않습니다.

<ul class="nav navbar-nav">
  <li>@Html.ActionLink("Home", "Index", "Home", null, new {@class="active"})</li>
  <li>@Html.ActionLink("About", "About", "Home")</li>
  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

이것은 올바른 형식의 클래스처럼 보이지만 작동하지 않습니다.

<a class="active" href="/">Home</a>

부트 스트랩 문서에서 탐색 표시 줄에 'a'태그를 사용해서는 안된다고 명시되어 있지만 위의 방법은 Html.ActionLink에 클래스를 추가하는 올바른 방법이라고 생각합니다. 내가 이것을 할 수있는 또 다른 (정확한) 방법이 있습니까?


3
해결하는 코드에는 class = active가 있습니다. 당신이 당신의 질문에 원하는 말이 아닌가? 코드를 작성하는 방법은 클래스를 추가하는 방법입니다.
— Matt Bodily

당신은 너무 명확하지 않습니다! 문제가 탐색에 추가 뭐죠 내가 정확히 내가 느끼기에도 불구하고, 이해 해달라고, 방법은 그냥 괜찮을 것입니다
— JC 도마뱀

1
해결 된 코드의 문제점은 무엇입니까? 당신은 무엇을 기대하고 있습니까? "작동하지 않는 것"보다 더 구체적 일 수 있습니까? 귀하의 질문은 현재 귀하를 도울만큼 명확하지 않습니다.
— dom

편집했습니다! 죄송합니다. "액티브"수업이 전혀 보이지 않는다는 것입니다.
— Gillespie

2
방금 부트 스트랩의 문서를 살펴 보았고 active클래스가 li아닌 요소에 클래스를 추가해야한다고 생각 합니다 a. 여기에 첫 번째 예를 참조하십시오 getbootstrap.com/components/#navbar
— DOM

답변:


300

부트 스트랩에서 active클래스는 <li>요소가 아닌 요소에 적용되어야 합니다 <a>. 여기에서 첫 번째 예를 참조 하십시오 : http://getbootstrap.com/components/#navbar

활성화 여부에 따라 UI 스타일을 처리하는 방법은 ASP.NET MVC의 ActionLink도우미 와 관련이 없습니다 . 이것이 Bootstrap 프레임 워크가 구축 된 방식을 따르는 적절한 솔루션입니다.

<ul class="nav navbar-nav">
    <li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

편집하다:

메뉴를 여러 페이지에서 재사용 할 가능성이 높으므로 메뉴를 여러 번 복사하여 수동으로 수행하지 않고 현재 페이지를 기준으로 선택한 클래스를 자동으로 적용하는 방법이 현명합니다.

가장 쉬운 방법은에 포함 된 값 ViewContext.RouteData, 즉 Actionand Controller값을 사용하는 것입니다. 우리는 현재 다음과 같은 것을 사용하여 만들 수 있습니다.

<ul class="nav navbar-nav">
    <li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Index" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
    <li class="@(ViewContext.RouteData.Values["Action"].ToString() == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
    <li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

코드가 좋지는 않지만 작업을 완료하고 원하는 경우 메뉴를 부분보기로 추출 할 수 있습니다. 훨씬 더 깔끔한 방법으로이 작업을 수행 할 수있는 방법이 있지만 시작하기 때문에 그대로 두겠습니다. 행운을 빕니다 ASP.NET MVC를 배우십시오!


늦은 편집 :

이 질문은 약간의 트래픽이 발생하는 것으로 보이므로 HtmlHelper확장 프로그램을 사용하여보다 우아한 솔루션을 사용하는 것으로 나타났습니다 .

편집 03-24-2015 : 선택한 동작을 트리거하는 여러 동작 및 컨트롤러를 허용하고 자식 동작 부분보기에서 메소드를 호출 할 때 처리 할 수 ​​있도록이 방법을 다시 작성해야했습니다. 업데이트를 공유 할 것이라고 생각했습니다!

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

.NET Core와 호환

public static string IsSelected(this IHtmlHelper htmlHelper, string controllers, string actions, string cssClass = "selected")
{
    string currentAction = htmlHelper.ViewContext.RouteData.Values["action"] as string;
    string currentController = htmlHelper.ViewContext.RouteData.Values["controller"] as string;

    IEnumerable<string> acceptedActions = (actions ?? currentAction).Split(',');
    IEnumerable<string> acceptedControllers = (controllers ?? currentController).Split(',');

    return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ?
        cssClass : String.Empty;
}

샘플 사용법 :

<ul>
    <li class="@Html.IsSelected(actions: "Home", controllers: "Default")">
        <a href="@Url.Action("Home", "Default")">Home</a>
    </li>
    <li class="@Html.IsSelected(actions: "List,Detail", controllers: "Default")">
        <a href="@Url.Action("List", "Default")">List</a>
    </li>
</ul>

고마워, 이것이 내가 원래 가지고있는 방법이라고 언급했지만, 선택된 객체간에 "active"클래스를 변경하는 코드 전체에 하나의 메소드가 있기를 바랐다.
— Gillespie

2
@Gillespie 걱정하지 마세요! 좀 더 도움이 될만한 정보를 추가하기 위해 답변을 편집했습니다.
— dom

5
첫 번째 편집과 관련하여 실제로는 색인 페이지에서만 작동했습니다. 그 이유는 ViewContext.RouteData.Values ​​[ "Action"]이 String 유형의 객체를 반환하지 않기 때문에 비교할 때 실패한 것 같습니다 (여전히 첫 페이지의 작동 방식을 모릅니다) . 모든 ViewContext.RouteData.Values ​​[ "Action"]을 ViewContext.RouteData.Values ​​[ "Action"]. toString ()으로 변경하면 모든 페이지에서 작동했습니다. 누군가 같은 문제가 발생하는 경우를 대비하여 솔루션에 이것을 추가하고 싶을 수도 있습니다.
— user3281466

2
@LonelyPixel 이 답변이 도움이 되었습니까?
— dom

1
VB.NET 사용자의 경우 : <li class = "@ (If (ViewContext.RouteData.Values ​​("Action "). ToString () ="Index ","active "," "))) @@ Html.ActionLink (" Home ","Index ","Home ") </ li>
— Andrea Antonangeli

28

신장:

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("<li role=\"presentation\"{0}>{1}</li>",
        currentAction.Equals(action, StringComparison.InvariantCulture) &&
        currentController.Equals(controller, StringComparison.InvariantCulture) ?
        " class=\"active\"" :
        String.Empty, html.ActionLink(text, action, controller).ToHtmlString()
    );
    return new MvcHtmlString(str);
}

용법:

<ul class="nav navbar-nav">
    @Html.LiActionLink("About", "About", "Home")
    @Html.LiActionLink("Contact", "Contact", "Home")
</ul>

1
이것은 매우 효율적인 확장입니다. 완벽하게 작동하고 매우 우아합니다. 당신에게 모자, 교수님! 내 유일한 그립role="presentation" 은 기본 탐색 메뉴 ( john.foliot.ca/aria-hidden/#pr ) 에는 전혀 적합하지 않습니다 . 비 순차 목록은 논리적으로 그룹화되어 관련 링크 세트에 매우 적합한 컨테이너입니다.
— René Kåbis

@ René Kåbis 부트 스트랩 내비게이션 getbootstrap.com/components/#nav-tabs
— Prof

1
사용자가 URL을 소문자 나 대문자로 수동으로 입력하면 작동하지 않습니다. " domain.com/Login "및 " domain.com/LOGIN " 해결책을 위해 var str = String.Format("<li role=\"presentation\"{0}>{1}</li>", currentAction.toLower().Equals(action.toLower(), StringComparison.InvariantCulture) && currentController.toLower().Equals(controller.toLower(), StringComparison.InvariantCulture) ? " class=\"active\"" : String.Empty, html.ActionLink(text, action, controller).ToHtmlString() );
— sky91

20

asp.net mvc에 view bag 매개 변수를 추가 하여이 작업을 수행했습니다. 여기서 내가 한 일

ViewBag.Current = "Scheduler";각 페이지에 유사한 매개 변수 추가

레이아웃 페이지에서

<ul class="nav navbar-nav">
     <li class="@(ViewBag.Current == "Scheduler" ? "active" : "") "><a href="@Url.Action("Index","Scheduler")" target="_self">Scheduler</a></li>
 </ul>

이것은 내 문제를 해결했습니다.


간단하고 쉬운 솔루션.
— japes Sophey

13

조금 늦을 수 있습니다. 그러나 이것이 도움이되기를 바랍니다.

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

그리고 다음과 같이 사용법 :

<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li class='@Html.IsActive("Home", "Index")'>
            @Html.ActionLink("Home", "Index", "Home")
        </li>
        <li class='@Html.IsActive("Home", "About")'>
            @Html.ActionLink("About", "About", "Home")
        </li>
        <li class='@Html.IsActive("Home", "Contact")'>
            @Html.ActionLink("Contact", "Contact", "Home")
        </li>
    </ul>
</div>

http://www.codingeverything.com/2014/05/mvcbootstrapactivenavbar.html 에서 참조하십시오.


1
매우 단순하고 우아한 솔루션. 모든 컨트롤러 작업에 대한 메뉴를 강조하기 위해 gist.github.com/jean-rakotozafy/… 를 개선했습니다 .
— Zan RAKOTO

5

이 질문이 오래되었다는 것을 알고 있지만 여기에 내 목소리를 추가하고 싶습니다. 링크가보기의 컨트롤러에 대해 활성화되어 있는지 여부를 아는 것이 좋습니다.

컨트롤러 동작의 각 뷰에 대해 고유 한 값을 설정하려고합니다. 예를 들어 홈페이지 링크를 활성화하려면 다음과 같이하십시오.

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

그런 다음 내 견해로는 다음과 같이 작성합니다.

<li @ViewBag.Home>@Html.ActionLink("Home", "Index", "Home", null, new { title = "Go home" })</li>

다른 페이지로 이동하면 프로그램, ViewBag.Home이 존재하지 않습니다 (ViewBag.Programs 대신)가 있습니다. 따라서 class = ""도 렌더링되지 않습니다. 나는 이것이 유지 보수성과 청결 모두에서 더 깨끗하다고 ​​생각합니다. 나는 항상 가능한 한 논리를 시야에서 벗어나고 싶어합니다.


4

Damith 게시 무엇을 고려, 나는 당신이 단지에 의해 활성받을 수 있다고 생각하기 좋아 Viewbag.Title (가장 좋은 방법은 당신의 있도록 콘텐츠 페이지에이를 채우는 것입니다 _Layout.cshtml페이지가 링크 막대를 잡고). 하위 메뉴 항목을 사용하는 경우 에도 잘 작동합니다.

<li class="has-sub @(ViewBag.Title == "Dashboard 1" || ViewBag.Title == "Dashboard 2" ? "active" : "" )">
    <a href="javascript:;">
        <b class="caret"></b>
        <i class="fa fa-th-large"></i>
        <span>Dashboard</span>
    </a>
    <ul class="sub-menu">
        <li class="@(ViewBag.Title == "Dashboard 1" ? "active" : "")"><a href="index.html">Dashboard v1</a></li>
        <li class="@(ViewBag.Title == "Dashboard 2" ? "active" : "")"><a href="index_v2.html">Dashboard v2</a></li>
    </ul>
</li>

깨끗하고 효율적입니다!
— mggluscevic

3

나는 dom의 "예쁘지 않은"답변을 수정 하고 더 추악하게 만들었습니다. 때로는 두 컨트롤러가 충돌하는 동작 이름 (예 : 색인)을 가지므로 다음과 같이하십시오.

<ul class="nav navbar-nav">
  <li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "HomeIndex" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
  <li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "AboutIndex" ? "active" : "")">@Html.ActionLink("About", "Index", "About")</li>
  <li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "ContactHome" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

3

당신은 이것을 시도 할 수 있습니다 : 제 경우에는 역할 기반 액세스를 기반으로 데이터베이스에서 메뉴를로드하고 있습니다.보기에 따라 활성화하려는 메뉴를 모든보기에 코드를 작성하십시오.

<script type="text/javascript">
        $(document).ready(function () {         
            $('li.active active-menu').removeClass('active active-menu');
            $('a[href="https://stackoverflow.com/MgtCustomer/Index"]').closest('li').addClass('active active-menu');
        });
</script>

3

이 솔루션은 Asp.net MCV 5에 간단합니다.

  1. 정적 클래스를 작성하십시오 (예 :) Utilitarios.cs.

  2. 클래스 내부에서 정적 메소드를 작성하십시오.

    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. 이런 식으로 전화

    <ul class="sidebar-menu" data-widget="tree">
        <li class="header">HEADER</li>
        <li class="@Url.IsLinkActive("Index", "Home")">
            <a href="@Url.Action("Index", "Home")"><i class="fa fa-link"></i> <span>Home</span></a>
        </li>
        <li class="@Url.IsLinkActive("About", "Home")">
            <a href="@Url.Action("About", "Home")"><i class="fa fa-link"></i><span>About</span></a>
        </li>
    </ul>

3

ASP.NET 코어 및 부트 스트랩 4

가장 최신 답변

확장 방법을 기반 으로이 문제를 해결하기 위해 업데이트 된 ASP.NET Core 및 Bootstrap 4 호환 방법을 위해 @crush 의 깔끔한 솔루션을 다시 작업했습니다 .IHtmlHelper

public static class LinkExtensions
{
    public static IHtmlContent ActiveActionLink(this IHtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        return ActiveActionLink(html, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static IHtmlContent ActiveActionLink(this IHtmlHelper html, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        var routeData = html.ViewContext.RouteData;
        var routeAction = (string)routeData.Values["action"];
        var routeController = (string)routeData.Values["controller"];

        var active = controllerName.Equals(routeController) && actionName.Equals(routeAction);

        using (var writer = new StringWriter())
        {
            writer.WriteLine($"<li class='nav-item {(active ? "active" : "")}'>");
            html.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes).WriteTo(writer, HtmlEncoder.Default);
            writer.WriteLine("</li>");
            return new HtmlString(writer.ToString());
        }
    }
}

용법

<nav class="navbar">
    <div class="collapse navbar-collapse">
        <ul class="navbar-nav">
            @Html.ActiveActionLink("Home", "Index", "Home", null, new { @class = "nav-link" })
            @Html.ActiveActionLink("About", "About", "Home", null, new { @class = "nav-link" })
            @Html.ActiveActionLink("Contact", "Contact", "TimeTracking", null, new { @class = "nav-link" })
        </ul>
    </div>
</nav>

1
아주 좋은 해결책입니다. 귀하의 예에서 기본적으로 '연락처'를 활성으로 설정하려면 어떻게해야합니까?
— Md. Suman Kabir

1
감사합니다. 좋은 점은 활성 요소를 설정할 필요가 없다는 것입니다. 즉시 '연락'페이지 방문으로, ActiveActionLink()받는 활성 클래스를 적용합니다 <li>:-)
— WoIIe

당신은 어디를 확인합니까?
— 모하마드

@Mohammad 이해가되지 않습니다. 질문을 자세히 설명해 주시겠습니까?
— WoIIe

LinkExtensions 클래스에서는 routeData에서 영역을 얻지 못했습니다!
— 모하마드

3

간편한 ASP.NET Core 3.0 및 TagHelper

[HtmlTargetElement("li", Attributes = "active-when")]
public class LiTagHelper : TagHelper
{
    public string ActiveWhen { get; set; }

    [ViewContext]
    [HtmlAttributeNotBound]
    public ViewContext ViewContextData { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (ActiveWhen == null)
            return;

        var targetController = ActiveWhen.Split("/")[1];
        var targetAction = ActiveWhen.Split("/")[2];

        var currentController = ViewContextData.RouteData.Values["controller"].ToString();
        var currentAction = ViewContextData.RouteData.Values["action"].ToString();

        if (currentController.Equals(targetController) && currentAction.Equals(targetAction))
        {
            if (output.Attributes.ContainsName("class"))
            {
                output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
            }
            else
            {
                output.Attributes.SetAttribute("class", "active");
            }
        }
    }
}

_ViewImports.cs에 포함하십시오 :

@addTagHelper *, YourAssemblyName

용법:

 <li active-when="/Home/Index">

2

ASP.NET MVC에서 비교를 개선하기 위해 '.ToString'추가

<ul class="nav navbar-nav">
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Index" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>

-


두 개의 다른 컨트롤러에 동일한 작업 이름이 있으면 작동하지 않습니다. 인덱스 동작이있는 홈 및 컨트롤러 정보를 사용하여 테스트하십시오.
— hyde

U는 면도기의 기능 서버를 다음 @functions { public bool IsActive(string action, string controller) { var actionRoute = ViewContext.RouteData.Values["Action"].ToString(); var controlRoute = ViewContext.RouteData.Values["Controller"].ToString(); return controller.Equals(controlRoute)&& actionRoute.Equals(actionRoute); } }과 같이 정의 할 수 있습니다 : 및 사용법 : <li class="@(IsActive("Index", "Home")? "active": "")">
— Hua Trung

2

또한 UrlHelperMvcHandler 자체에서 얻을 수있는 RequestContext에서 만들 수도 있습니다 . 따라서 Razor 템플릿 에서이 논리를 유지하려는 사람이 도움이 될 것이라고 믿습니다.

  1. 프로젝트 루트에서라는 폴더를 만듭니다 AppCode.
  2. 거기에 파일을 만듭니다 HtmlHelpers.cshtml
  3. 거기에 도우미를 만듭니다.

    @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);
    
            <div class="@(isCurrent ? "active" : "")">
                <div>@url.Action(action, controller)</div>
            </div>
         }   
    }
  4. 그런 다음 다음과 같이 뷰를 사용할 수 있습니다.

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

그것이 누군가에게 도움이되기를 바랍니다.


정말 멋지다. 여기에 성능 단점이 있습니까?
— 호감

@crush, 나는 그것을 측정하지는 않았지만 프레임 워크가 비슷한 논리를 사용하여에서 생성 한 UrlHelper것으로 생각하기 때문에 성능에 미치는 영향이 낮을 것으로 예상 됩니다 Controller.Url. 유일한 것은 우리가 아마도 UrlHelper각 호출에 대해 생성을 실행하고 싶지 않기 MenuItem때문에 도우미를 처음 호출 한 후 HttpContext Items에 저장하는 틱을 적용하여 요청 당 한 번만 수행 할 수 있다는 것입니다.
— Oleksii Aza

2

람다 함수로 가능

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

그런 다음 사용법

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

2

링크 주변이 아닌 링크 자체에 "활성"클래스를 추가하려는 사용자를위한 메소드를 HtmlHelper추가 하는 확장을 작성했습니다 .ActiveActionLink<li>


public static class LinkExtensions
{
    public static MvcHtmlString ActiveActionLink(this HtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        return ActiveActionLink(html, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString ActiveActionLink(this HtmlHelper html, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        const string activeClassName = "active";

        var routeData = html.ViewContext.RouteData;

        var routeAction = (string)routeData.Values["action"];
        var routeController = (string)routeData.Values["controller"];

        var active = controllerName.Equals(routeController) && actionName.Equals(routeAction);

        if (active)
        {
            var @class = (string)htmlAttributes["class"];

            htmlAttributes["class"] = string.IsNullOrEmpty(@class)
                ? activeClassName
                : @class + " active";
        }

        var link = html.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);

        return link;
    }
}

사용법은 다음과 같습니다.

@Html.ActiveActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-item nav-link" })

1

@dombenoit의 답변이 효과가 있습니다. 유지 관리 할 코드가 도입되었지만. 이 구문을 확인하십시오.

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", "#")
}

.SetLinksActiveByControllerAndAction()방법 의 사용에 주목하십시오 .

이 구문이 가능한 이유가 궁금하다면 TwitterBootstrapMVC를 확인하십시오.


답변 Dmitry에 감사드립니다, 저는 TwitterBootstrapMVC를 테스트하고 있습니다
— Gillespie

1

나는 또한 솔루션을 찾고 있었고 jQuery가 거의 도움이되었습니다. 먼저, <li>요소에 'id'를 주어야 합니다.

<li id="listguides"><a href='/Guides/List'>List Guides</a></li>

레이아웃 페이지 에서이 작업을 수행 한 후 jQuery에게 <li>뷰에서 '선택'해야 할 요소를 알릴 수 있습니다.

@section Scripts{
    <script type="text/javascript">
        $('#listguides').addClass('selected');
    </script>
}

참고 : 해당 섹션을 추가 @RenderSection("scripts", required: false)하려면 </body>태그 바로 앞에 레이아웃 페이지가 있어야합니다.


1

Dom의 답변의 첫 부분을 기반으로 한이 솔루션을 제안하고 싶습니다.

먼저 "action"과 "controller"의 두 변수를 정의하고이를 사용하여 활성 링크를 결정합니다.

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

그리고:

<ul class="nav navbar-nav">
    <li class="@((controller == "Home" && action == "Index") ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
    <li class="@((controller == "Home" && action == "About") ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
    <li class="@((controller == "Home" && action == "Contact") ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

이제 더 좋아 보이고 더 복잡한 솔루션이 필요하지 않습니다.


0

전혀 표시되지 않으면 두 개의 @ 기호가 필요하기 때문입니다.

@@class

그러나 "a"태그가 아닌 "li"태그에 활성 클래스가 있어야한다고 생각합니다. 너무 부트 스트랩 문서에 따라 ( http://getbootstrap.com/components/#navbar-default ) :

<ul class="nav navbar-nav">
  <li class="active"><a href="#">Home</a></li>
  <li><a href="#">Profile</a></li>
  <li><a href="#">Messages</a></li>
</ul>

따라서 코드는 다음과 같습니다.

<ul class="nav navbar-nav">
  <li class="active">@Html.ActionLink("Home", "Index", "Home", null)</li>
  <li>@Html.ActionLink("About", "About", "Home")</li>
  <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

@@ class에서 오류가 발생합니다. 원래 위의 코드 예제가 있었지만 작동하는 링크와 정확히 일치하지 않습니까?
— Gillespie

편집했습니다. @@는 필요하지 않습니다. 수업은 EA
— JC Lizard

0

이것이 도움이되기를 바랍니다. 아래는 메뉴가 가능한 방법입니다.

 <ul class="nav navbar-nav">
   <li><a href="@Url.Action("Index", "Home")" class="@IsMenuSelected("Index","Home", "active")">Home</a></li>
   <li><a href="@Url.Action("About", "Home")" class="@IsMenuSelected("About", "Home", "active")">About</a></li>
   <li><a href="@Url.Action("Contact", "Home")" class="@IsMenuSelected("Contact", "Home", "active")">Contact</a></li>
 </ul>

그리고 html 태그 아래에 MVC 도우미 기능을 추가하십시오.

 @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;
        }
    }

http://questionbox.in/add-active-class-menu-link-html-actionlink-asp-net-mvc/ 에서 답변을 참조했습니다.


0

나는이 문제가 우리 중 일반적인 문제라는 것을 깨달았으므로 nuget 패키지를 사용하여 자체 솔루션을 게시했습니다. 아래에서 작동 방식을 확인할 수 있습니다. 도움이 되길 바랍니다.

참고 :이 nuget 패키지는 첫 번째 패키지입니다. 따라서 실수를 발견하면 의견을 보내주십시오. 감사합니다.

  1. 패키지 설치 또는 소스 코드 다운로드 및 프로젝트 추가

    -Install-Package Betalgo.MvcMenuNavigator
  2. 열거 형에 페이지 추가

    public enum HeaderTop
    {
        Dashboard,
        Product
    }
    public enum HeaderSub
    {
        Index
    }
  3. 당신의 관제사 또는 행동의 상단에 필터를 넣어

    [MenuNavigator(HeaderTop.Product, HeaderSub.Index)]
    public class ProductsController : Controller
    {
        public async Task<ActionResult> Index()
        {
            return View();
        }
    
        [MenuNavigator(HeaderTop.Dashboard, HeaderSub.Index)]
        public async Task<ActionResult> Dashboard()
        {
            return View();
        }
    }
  4. 그리고 이것을 헤더 레이아웃에 사용하십시오.

    @{
    var headerTop = (HeaderTop?)MenuNavigatorPageDataNavigatorPageData.HeaderTop;
    var headerSub = (HeaderSub?)MenuNavigatorPageDataNavigatorPageData.HeaderSub;
    }
    <div class="nav-collapse collapse navbar-collapse navbar-responsive-collapse">
    <ul class="nav navbar-nav">
        <li class="@(headerTop==HeaderTop.Dashboard?"active selected open":"")">
            <a href="@Url.Action("Index","Home")">Dashboard</a>
        </li>
        <li class="@(headerTop==HeaderTop.Product?"active selected open":"")">
            <a href="@Url.Action("Index", "Products")">Products</a>
        </li>
    </ul>

추가 정보 : https://github.com/betalgo/MvcMenuNavigator


0

선택한 메뉴가 "활성화"되도록하는 더 깨끗하고 작은 코드가 여기 있다고 생각합니다.

 <ul class="navbar-nav mr-auto">
                <li class="nav-item @Html.IfSelected("Index")">
                    <a class="nav-link" href="@Url.Action("Index", "Home")">Home</a>
                </li>
                <li class="nav-item @Html.IfSelected("Controls")">
                    <a class="nav-link" href="@Url.Action("Controls", "Home")">MVC Controls</a>
                </li>
                <li class="nav-item @Html.IfSelected("About")">
                    <a class="nav-link" href="@Url.Action("About", "Home")">About</a>
                </li>
</ul>

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

일부 경우 컨트롤러 및 영역에 대해 확장해야 할 수도 있습니다.
— planetClaire

-1

위의 답변을 조합하여 솔루션을 만들었습니다.

그래서..

먼저 면도기 블록에서 컨트롤러의 이름 값과 사용자가 호출하는 동작을 포함하는 하나의 문자열 변수를 만듭니다.

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

그런 다음 HTML과 Razor 코드의 조합을 사용하십시오.

    <ul class="nav navbar-nav">
        <li class="@(controllerAction == "HomeIndex" ? "active" : "" )">@Html.ActionLink("Home", "Index", "Home")</li>
        <li class="@(controllerAction == "AboutIndex" ? "active" : "" )">@Html.ActionLink("About", "Index", "About")</li>
        <li class="@(controllerAction == "HomeContact" ? "active" : "" )">@Html.ActionLink("Contact", "Contact", "Home")</li>
    </ul>

컨트롤러 이름과 작업 이름을 얻기 위해 매번 "ViewContext.RouteData.Values"에 액세스 할 필요가 없기 때문에 이것이 좋습니다.


-1

이 문제에 대한 나의 해결책은

<li class="@(Context.Request.Path.Value.ToLower().Contains("about") ? "active " : "" ) nav-item">
                <a class="nav-link" asp-area="" asp-controller="Home" asp-action="About">About</a>
            </li>

더 좋은 방법은 링크와 비교할 현재 경로를 반환하기 위해 Html 확장 메서드를 추가하는 것입니다


-1

나는 이걸했다:

메뉴 부분보기에서 도우미 만들기

 @helper RouterLink(string action, string controller)
{
    var IsActive = ViewContext.RouteData.Values["Controller"].ToString() == controller && ViewContext.RouteData.Values["Action"].ToString() == action;
    <text>href="@Url.Action(action, controller)"</text>if (IsActive){ <text>class="active"</text>}
}

그런 다음 앵커 태그에서 다음과 같이 사용하십시오.

<li><a @RouterLink("Index","Home")>Home</a></li>

내 응용 프로그램에는 영역이 없지만 도우미 함수에 다른 변수로 포함될 수도 있습니다. 그리고 내 견해로는 활성 클래스를 앵커 태그에 전달해야했습니다. 그러나 li이와 같이 구성 할 수도 있습니다.


1
알다시피, downvote는 이유를 언급하지 않으면 실제로 도움이되지 않습니다.
— Anup Sharma
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.