如何在ASP.NET MVC中将“活动”类添加到Html.ActionLink


128

我正在尝试在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的正确方法。我还有其他(整洁)的方式可以做到这一点吗?


3
解析的代码中有class = active。这不是您想在问题中说的吗?您如何编写代码,是我添加类的方式
Matt Bodily 2013年

你不太清楚!!!我不十分了解将其添加到导航中的问题是什么,尽管我有一种感觉,但这种方式应该还不错
JC Lizard 2013年

1
解析的代码有什么问题?你在期待什么?您能否比“似乎没有用”更具体?您的问题尚不清楚,无法立即为您提供帮助。
dom

编辑!抱歉,我的意思是根本没有显示“活动”课
Gillespie 2013年

2
只需看一眼Bootstrap的文档,我认为您需要将active类添加到li元素,而不是添加a。请参阅此处的第一个示例:getbootstrap.com/components/#navbar
dom

Answers:


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,即ActionController值。我们可以在您当前所拥有的基础上进行以下改进:

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

谢谢,正如我之前提到的,这是我最初的想法,但是我希望在我的代码中拥有一种方法,可以在选定对象之间更改“活动”类。
Gillespie 2013年

2
@Gillespie不用担心!我已经编辑了答案,添加了一些可能对您有所帮助的信息。
dom

5
关于第一次编辑,它实际上仅适用于“索引”页面。似乎原因是进行比较时失败,因为ViewContext.RouteData.Values [“ Action”]未返回String类型的对象(仍然不知道它如何在第一页工作)。 。当我将所有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

@勒Kåbis它引导naigation getbootstrap.com/components/#nav-tabs
教授

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

最新答案

我已经对@crush的简洁解决方案进行了重新设计,以开发一种更新的,与ASP.NET CoreBootstrap 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
很好的解决方案。在您的示例中,如何默认将“联系人”设置为活动状态?
Suman Kabir博士

1
谢谢。好处是您不需要设置活动元素。由于作为“联系我们”页面被访问不久,ActiveActionLink()将活动类适用于<li>:-)
WoIIe

您在哪里检查区域?
穆罕默德

@默罕默德,我不明白。您能详细说明您的问题吗?
WoIIe

在LinkExtensions类中,您没有从routeData获得区域!
穆罕默德

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

添加“ .ToString”以改进在ASP.NET MVC上的比较

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

-


如果两个不同的控制器中有相同的动作名称,则此方法将无效。使用Home和About控制器通过Index操作对其进行测试。
海德

您可以在剃刀上定义功能服务器,例如:@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

我们还可以UrlHelper从RequestContext 创建,可以从MvcHandler本身获取。因此,我希望有人希望将这种逻辑保留在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项目中的动作,因此每个请求只执行一次。
奥莱克西氮杂

2

可以使用lambda函数

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


感谢您的答案德米特里,我正在测试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

但是,我相信您可能需要在“ li”标记上而不在“ a”标记上具有活动类。根据太引导文档(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 2013年

编辑。@@不是必需的。您必须将课程设置为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. 将过滤器放在Controllor或Action的顶部

    [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并没有真正的帮助。
安纳·夏尔玛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.