如何在_Layout.cshtml中的列表项中动态设置样式

时间:2012-05-10 17:26:00

标签: jquery asp.net-mvc-3 razor

我在_Layout.cshtml中有这个菜单:

<td class="MenuStructure">
    <ul id="menu">
        <li>@Html.ActionLink("First Page", "Page1Action", "Main")</li>
        <li>@Html.ActionLink("Second Page", "Page2Action", "Main")</li>
        <li>@Html.ActionLink("Third Page", "Page3Action", "Second")</li>
    </ul>
</td>

点击其中一个操作链接后,我想设置&lt; li&gt;的类。其中包含“选定”和其他的类&lt; li&gt;元素“”。

这有效:

    <script type="text/javascript">
        $(document).ready(function () {
        var selMenu = '@ViewBag.SelectedMenu';
            if (selMenu == "page1") {
                $("#page1").attr('class', 'selected');
                $("#page2").attr('class', '');
                $("#page3").attr('class', '');
            }
            if (selMenu == "page2") {
                $("#page1").attr('class', '');
                $("#page2").attr('class', 'selected');
                $("#page3").attr('class', '');
            }
        });
    </script>

但它非常难看。有人能告诉我一个更优雅的方式吗?

2 个答案:

答案 0 :(得分:2)

如果您将click事件处理程序添加到a元素组中,则可以轻松地将该类添加到单击元素的li中,并为所有兄弟节点删除它,无论其中有多少。这消除了对每个attr的if语句和li更新的需要。

以下是一个示例:

http://jsfiddle.net/JjBgm/4/

标记:

<ul id="menu">
    <li><a href="#">one</a></li>
    <li><a href="#">two</a></li>
    <li><a href="#">three</a></li>
</ul>

jQuery的:

$(document).ready(function() {

    $('#menu li a').click(function() {
        $(this).parent().addClass('selected').siblings().removeClass('selected');
    });

});

显然,您必须使用MVC修改此方法以满足您的需求,但这个概念应该可行。

编辑:因为您提到服务器往返涉及上述可能效果不佳。在这种情况下,您可以根据所选菜单构建客户端ID并从那里控制该类。

$(document).ready(function () {
    var selMenu = '@ViewBag.SelectedMenu';
    $("#" + selMenu).addClass('selected').siblings().removeClass('selected');
});

假设#page1#page2等,请参阅<li>元素,而不会在服务器处理后看到生成的标记。

如果#page1引用<a>标记,则您的声明为:

$("#" + selMenu).parent().addClass('selected').siblings().removeClass('selected');

当然未经测试。要点是动态构建选择器,然后根据需要使用兄弟和父选择器来清除类。它更干净。

答案 1 :(得分:0)

我认为这是您网站的主要导航,并且您希望保持顶级菜单“选中”,即使您没有采取确切的操作(例如,链接转到列表,但是然后您转到'编辑'页面等)。

有两种方法可以做到这一点。一种是在viewbag中放置一个属性,然后在渲染时在_layout.cshtml文件中检查它。

// in controller Action method
ViewBag.SelectedMenu = "first"
// in view
<li class="@((ViewBag.SelectedMenu == "first") ? "selected-class" : "")">first link</li>

第二种方式(我们使用)是使用Sitemap包(从NuGet安装)。然后,您可以在根目录中编辑Sitemap文件,并将所有链接放在那里(即使是那些不直接用于导航的链接)。然后,您可以让控件为您呈现<ul><li>'s。它提供了你现在拥有的相同的HTML,很大程度上,所以css应该仍然有用。

  • 所有菜单内容都在一个地方
  • 站点地图尊重[authorize]属性或其他过滤器,隐藏仅登录的链接
  • 可以在菜单中隐藏/显示可能不存在的节点(重新映射的网址等)
  • 很多其他不错的小功能

Mvc.sitemap档案:

<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="Get a car" controller="Cars" action="Buy"/>
    <mvcSiteMapNode title="Reports" controller="Report" action="AllReports">
      <mvcSiteMapNode title="" controller="Report" action="ViewMPG"/>
    </mvcSiteMapNode>
</mvcSiteMapNode>

然后,在_Layout.cshtml文件中:

<td class="MenuStructure">
    <!-- one level menu starting at top (home), including the "home" link -->
    @Html.MvcSiteMap().Menu(0, true, true, 1)
</td>

然后修改Views\Shared\MenuHelperModel.cshtml以更改样式:

<ul id="menu">
    @foreach (var node in Model.Nodes)
    {
        var show = node.IsInCurrentPath && (!node.IsRootNode || node.IsCurrentNode);
        var cls = show ?  "selected" : ""; 
        <li class="@cls">@Html.DisplayFor(m => node)</li>
    }
</ul>