在我的asp.net mvc解决方案中集成一般菜单

时间:2011-04-14 10:50:44

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

为了我的学习,我正在使用ASP.NET MVC3构建文档管理解决方案。以下是我管理的网页:

  
      
  • 搜索/结果页面(项目列表)
  •   
  • 最喜欢的页面(项目列表)
  •   
  • 编辑页面
  •   
  • 创建页面
  •   

我还有一个Site.Master页面,我在屏幕左侧显示了一个树视图菜单。因此,无论用户在网站中的哪个位置,树视图菜单都通过在菜单中加下划线来显示他的位置。

为了构建树视图菜单,我使用下面的代码(为便于阅读而清理):

        <ul id="treemenu1" class="treeview">                                    
                <li>Documents
                    <ul>  
                        <%= Html.TreeviewMenu(TreeMenu.Create("Search", "Search", "Affaires", null))%>
                        <%= Html.TreeviewMenu(TreeMenu.Create("Favorite", "Favorite", "Affaires", null))%>
                        <%= Html.TreeviewMenu(TreeMenu.Create("New", "Create", "Affaires", null))%>
                   </ul>  
                </li>
        </ul>

问题是我需要在菜单中为活动项加下划线。因此,如果用户正在显示搜索页面,则我的搜索菜单条目必须加下划线。我该怎么办?我正在考虑将这些信息集成到传递给每个视图页面的强类型视图模型中,但它失败了,因为每个页面都使用不同的视图模型。我不喜欢使用会话变量,因为它不是一个干净的解决方案。

有什么想法吗?

具有会话变量的解决方案:我将“当前菜单项”保存在会话变量中(来自我的控制器)。因此,每当重新加载Site.Master页面时,它都会重新创建每个树视图菜单项。对于每一个,它检查项目是否等于会话变量。如果是,则将“已选择”类添加到项目中(用蓝色突出显示的css。)

我真的不喜欢使用会话变量。也许有更优雅的解决方案?

2 个答案:

答案 0 :(得分:1)

如何使用帮助器:

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("Search", "Search", "Affaires") %>
    <%= Html.MenuItem("Favorite", "Favorite", "Affaires") %>
    <%= Html.MenuItem("New", "Create", "Affaires") %>
</ul>
如果您导航到/Affaires/Favorite

可能会产生以下结果

<ul>
    <li><a href="/Affaires/Search">Search</a></li>
    <li class="active"><a href="/Affaires/Favorite">Favorite</a></li>
    <li><a href="/Affaires/Create">New</a></li>
</ul>

答案 1 :(得分:0)

嗯,有一个简单有效的解决方案:让每个页面发出信号,告知它是否是活动页面,并使用jQuery设置css类。

假设你渲染的html看起来像:

<ul id="treemenu1" class="treeview">                                    
    <li>Documents
        <ul>
            <li class="search"></li>
            <li class="favorite"></li>
        </ul>
    </li>
</ul>

在每个页面的底部,执行类似的操作(这将位于搜索视图中):

<script type="text/javascript">
    $(document).ready(function () {
        // Set active nav
        $('#treemenu1 li.search').addClass('selected');
    });
</script>

根据新信息更新

比会话变量更清晰可能是使用控制器中的ViewBag属性。

public ActionResult Search(/*whatever*/)
{
    // do things

    // set the selevted view
    ViewBag.SelectedMenuItem = "search";

    return View();
}

然后在您的母版页中,您可以查看<%: ViewBag.SelectedMenuItem %>

请注意,SelectedMenuItem是一个随机名称。 The ViewBag property is of type dynamic所以你可以使用你喜欢的任何属性名称。