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 CoreBootstrap 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.