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

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에 클래스를 추가하는 올바른 방법이라고 생각합니다. 내가 이것을 할 수있는 또 다른 (정확한) 방법이 있습니까?



답변

부트 스트랩에서 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>


답변

신장:

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>


답변

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>

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


답변

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

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 에서 참조하십시오.


답변

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

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

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 = “”도 렌더링되지 않습니다. 나는 이것이 유지 보수성과 청결 모두에서 더 깨끗하다고 ​​생각합니다. 나는 항상 가능한 한 논리를 시야에서 벗어나고 싶어합니다.


답변

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>


답변

나는 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>