developer tip

MVC 3 Razor에서 활성 페이지 링크를 얻는 더 나은 방법

copycodes 2021. 1. 10. 17:27
반응형

MVC 3 Razor에서 활성 페이지 링크를 얻는 더 나은 방법


특정 메뉴 링크가 특정 페이지에서 활성화되도록하려면 Razor에서이 접근 방식을 사용하고 있습니다.

마스터 레이아웃에는 다음과 같은 검사가 있습니다.

var active = ViewBag.Active;
const string ACTIVE_CLASS = "current";

if (active == "home")
{
    ViewBag.ActiveHome = ACTIVE_CLASS;
}
if (active == "products")
{
    ViewBag.ActiveProducts = ACTIVE_CLASS;
}

기타

마스터 레이아웃의 html 메뉴 :

<ul>
<li class="@ViewBag.ActiveHome"><a href="/">Home</a></li>
<li class="@ViewBag.ActiveProducts"><a href="@Url.Action("index", "products")">Products</a></li>
</ul>

다른보기에서 사용할 레이아웃 페이지를 지정할 때 :

@{
    ViewBag.Active = "home";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

현재 사용중인 링크보다 활성 링크를 구분하는 더 나은 방법이 있습니까?


더 나은 방법은 HTML 도우미를 사용하는 것입니다.

using System.Web.Mvc; 
using System.Web.Mvc.Html;

public static class MenuExtensions
{
    public static MvcHtmlString MenuItem(
        this HtmlHelper htmlHelper, 
        string text,
        string action, 
        string controller
    )
    {
        var li = new TagBuilder("li");
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.GetRequiredString("action");
        var currentController = routeData.GetRequiredString("controller");
        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }
        li.InnerHtml = htmlHelper.ActionLink(text, action, controller).ToHtmlString();
        return MvcHtmlString.Create(li.ToString());
    }
}

그리고:

<ul>
    @Html.MenuItem("Home", "Home", "Home")
    @Html.MenuItem("Products", "Index", "Products")
</ul>

위의 작업을 수행하려면 확장을 인식하는 뷰가 필요합니다. 뷰 폴더의 Web.config에서 <add namespace="yourNamespacehere.Helpers" />네임 스페이스 태그 내부 에 추가 합니다. 그런 다음 프로젝트를 빌드하고이를 추가 할 뷰를 닫았다가 다시 엽니 다.

그런 다음 현재 작업 및 컨트롤러를 기반으로 도우미는 active앵커를 생성 할 때 클래스를 추가하거나 추가하지 않습니다 .


Darin의 예제를 확장하면 도우미의 RouteValues ​​및 HtmlAttributes에 대한 추가 선택적 매개 변수를 추가하는 전체 클래스가 있습니다. 실제로 기본 ActionLink처럼 작동합니다.

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MYNAMESPACE.Helpers {
    public static class MenuExtensions {
        public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper,
                                             string text, string action,
                                             string controller,
                                             object routeValues = null,
                                             object htmlAttributes = null) {
            var li = new TagBuilder("li");
            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString("action");
            var currentController = routeData.GetRequiredString("controller");
            if (string.Equals(currentAction,
                              action,
                              StringComparison.OrdinalIgnoreCase) &&
                string.Equals(currentController,
                              controller,
                              StringComparison.OrdinalIgnoreCase)) {
                li.AddCssClass("active");
            }
            if (routeValues != null) {
                li.InnerHtml = (htmlAttributes != null)
                    ? htmlHelper.ActionLink(text,
                                            action,
                                            controller,
                                            routeValues,
                                            htmlAttributes).ToHtmlString()
                    : htmlHelper.ActionLink(text, 
                                            action, 
                                            controller, 
                                            routeValues).ToHtmlString();
            }
            else {
                li.InnerHtml = htmlHelper.ActionLink(text, 
                                                     action, 
                                                     controller).ToHtmlString();
            }
            return MvcHtmlString.Create(li.ToString());
        }
    }
}

그리고 View 폴더의 web.config에서 :

<system.web.webPages.razor>
  <host ... />
  <pages ... >
    <namespaces>
      ...

      ...
      <add namespace="MYNAMESPACE.Helpers" />
    </namespaces>
  </pages>
</system.web.webPages.razor>

텍스트에 HTML 형식을 포함하려면이 InnerHtml을 사용하십시오.

li.InnerHtml = "<a href=\"" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(action, controller).ToString() + "\">" + text + "</a>";

텍스트는 "<b> 굵게 </ b> 보통"일 수 있습니다.


RC2 업데이트 -MVC6 / Asp.Net 5에서이 작업을 수행하는 방법을 궁금해하는 사람들을 위해 유사하지만 미묘하게 다릅니다. 이 이젠 없다 MvcHtmlString하고는 RouteData완전히 다르게 작동합니다. 또한, 상황에 맞는 개체가 지금해야 IHtmlContent보다는 HtmlHelper.

using System;
using Microsoft.AspNet.Mvc.Rendering;

public static class MenuExtensions
{
    public static IHtmlContent MenuItem(
        this IHtmlHelper htmlHelper,
        string text,
        string action,
        string controller
    )
    {

        var li = new TagBuilder("li") { TagRenderMode = TagRenderMode.Normal };
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.Values["action"].ToString();
        var currentController = routeData.Values["controller"].ToString();

        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }


        li.InnerHtml.AppendHtml(htmlHelper.ActionLink(text, action, controller));

        return li;


    }
}

This code worked great for me, even on a new Visual Studio 2013 MVC5/Bootstrap project. Note also that you could change the li.AddCssClass("active"); line to point to a custom class if you want to leave the Bootstrap "active" class alone. I added one called "activemenu" in the project's Site.css file and did any specific navbar styling changes I wanted there.

The line in the code above was just changed to this to get it all working:

li.AddCssClass("activemenu");

In Site.css I added a simple class for my purpose:

.activemenu {
    text-decoration: underline;
}

Alternatively you could change the background color and/or border, etc...


here is an extention on Darin's class to insert html in the link text rather than a simple text

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace YourNameSpaceHere
{
    public static class MenuExtensions
    {
        public static MvcHtmlString MenuItem(
            this HtmlHelper htmlHelper,
            string html,
            string action,
            string controller
        )
        {
            var li = new TagBuilder("li");
            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString("action");
            var currentController = routeData.GetRequiredString("controller");
            if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
                string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
            {
                li.AddCssClass("active");
            }
            //generate a unique id for the holder and convert it to string
            string holder = Guid.NewGuid().ToString();
            string anchor = htmlHelper.ActionLink(holder, action, controller).ToHtmlString();
            //replace the holder string with the html
            li.InnerHtml = anchor.Replace(holder, html);
            return MvcHtmlString.Create(li.ToString());
        }
    }
}

and use it like this:

<ul>
    @Html.MenuItem("<span class'ClassName'>Home</span>", "Home", "Home")
</ul>

ReferenceURL : https://stackoverflow.com/questions/6323021/better-way-to-get-active-page-link-in-mvc-3-razor

반응형