ASP.NET MVCのHtml.ActionLinkに「アクティブ」クラスを追加する方法


128

MVCのブートストラップnavbarに「アクティブ」クラスを追加しようとしていますが、次のように記述すると、アクティブクラスが表示されません。

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

Bootstrapのドキュメントには、ナビゲーションバーで「a」タグを使用しないように記載されていますが、上記はHtml.ActionLinkにクラスを追加する正しい方法であると私が考える方法です。これを行うことができる別の(きちんとした)方法はありますか?


3
解決するコードには、class = activeが含まれています。それはあなたがあなたの質問であなたが望むことではありませんか?あなたのコードは、クラスを追加する方法です
Matt Bodily

あなたはあまり明確ではありません!!! 私はそれをnavに追加する際の問題が何であるかを正確に理解していませんが、感じはしますが、問題はありません
JC Lizard

1
解決されたコードの何が問題ですか?何を期待していますか?「うまくいかない」より具体的に説明できますか?あなたの質問は現在あなたを助けるのに十分なほど明確ではありません。
ドム

編集しました!申し訳ありませんが、私が意味したのは、「アクティブ」クラスがまったく表示されないことでした
Gillespie、

2
Bootstrapのドキュメントを見ただけで、ではなく要素にactiveクラスを追加する必要があると思います。ここの最初の例を参照してください:getbootstrap.com/components/#navbarlia
dom

回答:


300

Bootstrapでは、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>

ありがとう、これは元々持っていた方法ですが、選択したオブジェクト間で「アクティブ」クラスを変更するコード全体で1つのメソッドを使用したいと思っていました。
Gillespie

2
@ギレスピー心配無用!回答を編集して、もう少し役立つ情報を追加しました。
ドム

5
最初の編集に関しては、実際には索引ページでのみ機能しました。理由は、比較を行っているときにViewContext.RouteData.Values ["Action"]が文字列型オブジェクトを返さないために失敗したためと思われます(それでも最初のページでどのように機能したかわかりません...)。 。すべてのViewContext.RouteData.Values ["Action"]をViewContext.RouteData.Values ["Action"]。toString()に変更すると、すべてのページで機能しました。誰かが同じ問題を経験した場合に備えて、これをソリューションに追加したい場合があります。
user3281466 2014年

2
@LonelyPixel多分この答えはあなたのために働くのですか?
dom

1
VB.NETユーザーの場合:<li class = "@(If(ViewContext.RouteData.Values(" Action ")。ToString()=" Index "、" active "、" "))"> @ Html.ActionLink( "ホーム」、「インデックス」、「ホーム」)</ 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)にはまったく適切ではありません。順序付けられていないリストは、論理的にグループ化されているため、関連する一連のリンクに非常に適しています。
ルネKåbis

@RenéKåbisit for bootstrap naigation 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にビューバッグパラメーターを追加してこれを行うように管理しました。ここで私は何をしましたか

追加されました 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ソフィー

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の 「きれいではない」答えを変更して、醜くしました。2つのコントローラーが競合するアクション名(つまり、インデックス)を持っていることがあるので、これを行います。

<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 Core&Bootstrap 4

最新の回答

私は再働いてい@crush更新のためのきちんとしたソリューションASP.NETコアブートストラップ4に基づいてこの問題を解決するための互換性のある方法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
非常に良い解決策です。あなたの例では、「連絡先」をデフォルトでアクティブに設定するにはどうすればよいですか?
Kabir

1
ありがとうございました。良い点は、アクティブな要素を設定する必要がないことです。「連絡先」ページにアクセスActiveActionLink()するとすぐに、アクティブクラスが<li>:-)に適用されます
WoIIe

どこをチェックしますか?
Mohammad

@Mohammadわかりません。質問を詳しく説明していただけませんか?
WoIIe

LinkExtensionsクラスでは、routeDataからエリアを取得していません。
Mohammad

3

Easy ASP.NET Core 3.0とTagHelpers

[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>

-


2つの異なるコントローラーに同じアクション名がある場合、これは機能しません。ホームとインデックスアクション付きのコントローラーについてテストします。
ハイド2015

次のようなかみそりで関数サーバーを定義できます:@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に保存するティックを適用して、リクエストごとに1回だけ実行することです。
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

リンクを囲むのではなく、リンク自体に「アクティブ」クラスを追加したい人のためHtmlHelperActiveActionLinkメソッドを追加する拡張機能を作成しました<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>

レイアウトページでこれを行った後<li>、ビューで「選択」する要素をjQueryに指示できます。

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

注:セクションを追加する@RenderSection("scripts", required: false)には、レイアウトページの</body>タグの直前に配置する必要があります。


1

ドムの答えの最初の部分に基づいたこの解決策を提案したいと思います。

まず、「action」と「controller」という2つの変数を定義し、それらを使用してアクティブなリンクを決定します。

{ 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

まったく表示されない場合、その理由は2つの@記号が必要なためです。

@@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はエラーをスローします。最初に上記のコード例を使用しましたが、これは機能しますが、Actionlinksが「すべき」と正確に一致しませんか?
Gillespie、

編集。@@は不要です。EAにクラスを配置する必要があります
JCリザード

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

上記の答えを組み合わせて解決策を作りました。

そう..

最初にかみそりブロックで、コントローラーの名前値とユーザーが呼び出すアクションを含む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
理由を述べない限り、反対票は実際には役に立ちません。
Anup Sharma
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.