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

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

MVC のブートストラップ ナビゲーション バーに「アクティブ」クラスを追加しようとしていますが、次のように記述してもアクティブ クラスが表示されません。

<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 にクラスを追加する正しい方法であると私は考えています。これを行う別の (きちんとした) 方法はありますか?

ベストアンサー1

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、つまりActionと の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拡張機能を使用してよりエレガントな解決策を提案することにしました。

編集 2015 年 3 月 24 日: 複数のアクションとコントローラーが選択された動作をトリガーできるように、またメソッドが子アクションの部分ビューから呼び出された場合の処理​​を可能にするために、このメソッドを書き直す必要がありました。更新を共有しようと思いました。

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>

おすすめ記事