Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 加入“;主动的;asp.net mvc母版页中导航列表的标记_Asp.net Mvc - Fatal编程技术网

Asp.net mvc 加入“;主动的;asp.net mvc母版页中导航列表的标记

Asp.net mvc 加入“;主动的;asp.net mvc母版页中导航列表的标记,asp.net-mvc,Asp.net Mvc,在默认asp.net mvc项目的Site.Master文件中,有一个菜单导航列表: <div id="menucontainer"> <ul id="menu"> <li><%= Html.ActionLink("Home", "Index", "Home")%></li> <li><%= Html.ActionLink("About Us", "A

在默认asp.net mvc项目的Site.Master文件中,有一个菜单导航列表:

<div id="menucontainer">
    <ul id="menu">              
        <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>

这将在浏览器中渲染为:

<div id="menucontainer"> 
    <ul id="menu">              
        <li><a href="/">Home</a></li> 
        <li><a href="/Home/About">About Us</a></li> 
    </ul> 
</div> 

我希望能够根据调用的视图动态设置活动列表项。也就是说,当用户查看主页时,我希望创建以下HTML:

<div id="menucontainer"> 
    <ul id="menu">              
        <li class="active"><a href="/">Home</a></li> 
        <li><a href="/Home/About">About Us</a></li> 
    </ul> 
</div> 

我希望这样做的方式是:

<div id="menucontainer">
    <ul id="menu">              
        <li <% if(actionName == "Index"){%> class="active"<%}%>><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li <% if(actionName == "About"){%> class="active"<%}%>><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>

这里的关键位是
class=“active”
行。我不知道如何确定当前actionName是什么


有什么建议吗?或者,如果我完全走错了方向,有没有更好的方法来实现这一点?

您的视图必须了解控制器的操作,这一事实正在打破MVC模式。也许您的控制器可以将一些“控制”信息传递给视图,最终允许它完成相同的事情,唯一的区别是谁负责

就像控制器的动作一样,您可以:

public ActionResult Index(){
     ViewData["currentAction"] = "Index";
     //... other code
    return View();
}
<% if( ((string)ViewData["currentAction"]) == "Index" {%> <!- some links --><% } %>
<% if( ((string)ViewData["currentAction"]) == "SomethingElse" {%> <!- some links --><% } %>
在你看来,你可以:

public ActionResult Index(){
     ViewData["currentAction"] = "Index";
     //... other code
    return View();
}
<% if( ((string)ViewData["currentAction"]) == "Index" {%> <!- some links --><% } %>
<% if( ((string)ViewData["currentAction"]) == "SomethingElse" {%> <!- some links --><% } %>

然而,我想得越多,我就越怀疑为什么要对多个操作使用相同的视图。的观点是否类似

如果用例证明它是正确的,那么就按照我上面的建议去做。但是,否则,您可能会将问题分解为多个视图(每个控制器操作一个视图),问题会自行解决。

试试看

应该很好

编辑:在BETA1中删除


已从ViewContext类中删除ViewName属性。

在视图中,您可以使用以下内容获取当前操作名称:

ViewContext.RouteData.Values["action"].ToString()

根据前面的回答,以下是我目前针对同一问题的解决方案:

在母版页中,我给每个li一个对应于控制器和操作的id,因为这应该从ActionLink中知道。我以前是这样做的网页标题,但这有助于组织

网站主:

<ul id="menu">
    <li id="menuHomeIndex" runat="server"><%= Html.ActionLink("Home", "Index", "Home") %></li>
    <li id="menuHomeAbout" runat="server"><%= Html.ActionLink("About Us", "About", "Home") %></li>
</ul>
它比内联代码要复杂得多,但我认为它更简洁,还允许在不同的控制器中使用相同名称的操作。因此,如果添加更多具有不同控制器的菜单项,则并非所有名为Index的操作都将在菜单中高亮显示


如果有人发现此方法存在问题,请告诉我。

您还可以尝试从控制器名称和视图名称中检测当前选定的选项卡,然后添加class属性

public static string MenuActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
    var htmlAttributes = new RouteValueDictionary();

    if (helper.ViewContext.Controller.GetType().Name.Equals(controllerName + "Controller", StringComparison.OrdinalIgnoreCase))
    {
        htmlAttributes.Add("class", "current");
    }

    return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), htmlAttributes);
}

这应该可以在客户端使用jQuery,使用Google提供最新的jQuery库:

<script src="http://www.google.com/jsapi" type="text/javascript" language="javascript"></script>
<script type="text/javascript" language="javascript">google.load("jquery", "1");</script>  

<script language="javascript" type="text/javascript">
      $(document).ready(function(){
          var str=location.href.toLowerCase(); 
        $('#menucontainer ul#menu li a').each(function() {
                if (str.indexOf(this.href.toLowerCase()) > -1) {
                        $(this).attr("class","current"); //hightlight parent tab
                     }  
                });
      });  
    </script>

load(“jquery”,“1”);
$(文档).ready(函数(){
var str=location.href.toLowerCase();
$('menucontainer ul#menu li a')。每个(函数(){
if(str.indexOf(this.href.toLowerCase())>-1){
$(this.attr(“class”,“current”);//高亮父选项卡
}  
});
});  

我让自己成为处理这类事情的助手方法。在我的母版页后面的代码中(可以被推到一个扩展方法…可能是更好的方法),我放了以下代码

protected string ActiveActionLinkHelper(string linkText, string actionName, string controlName, string activeClassName)
{
    if (ViewContext.RouteData.Values["action"].ToString() == actionName && 
            ViewContext.RouteData.Values["controller"].ToString() == controlName)
        return Html.ActionLink(linkText, actionName, controlName, new { Class = activeClassName });

    return Html.ActionLink(linkText, actionName, controlName);
}
然后,我就这样在我的页面中调用它:

<%= ActiveActionLinkHelper("Home", "Index", "Home", "selected")%>
public class LayoutAttribute : ActionFilterAttribute
{
    private CurrentPage _currentPage { get; set; }

    public LayoutAttribute(
        CurrentPage CurrentPage
    ){
        _currentPage = CurrentPage;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (result == null || result.Model == null || !(result.Model is LayoutModel)) return;

        ((LayoutModel)result.Model).CurrentPage = _currentPage;
    }
}


使用MVC3和Razor视图,您可以实现如下功能:

<ul id="menu">
 @if (ViewContext.RouteData.Values["action"].ToString() == "Index")
 {
 <li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
 }
 else
 {
 <li>@Html.ActionLink("Home", "Index", "Home")</li>
 }
 @if (ViewContext.RouteData.Values["action"].ToString() == "About")
 {
 <li class="active">@Html.ActionLink("About", "About", "Home")</li>
 }
 else
 {
 <li>@Html.ActionLink("About", "About", "Home")</li>
 }
</ul>

在MVC 3 Razor视图引擎中,您可以按以下方式执行:

@{string ctrName = ViewContext.RouteData.Values["controller"].ToString();}

<div id="menucontainer">
  <ul id="menu"> 
    <li @if(ctrName == "Home"){<text> class="active"</text>}>@ Html.ActionLink("Home",  "Index", "Home")</li>
    <li @if(ctrName == "About"){<text> class="active"</text>}>@ Html.ActionLink("About Us", "About", "Home")</li>
  </ul>
</div>

以下是与MVC4当前版本兼容的版本。
我重写了Adam Carr的代码作为扩展方法

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;

namespace MyApp.Web {
    public static class HtmlHelpers {
        /// <summary>
        /// Returns an anchor element (a element) that contains the virtual path of the
        /// specified action. If the controller name matches the active controller, the
        /// css class 'current' will be applied.
        /// </summary>
        public static MvcHtmlString MenuActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName) {
            var htmlAttributes = new RouteValueDictionary();
            string name = helper.ViewContext.Controller.GetType().Name;

            if (name.Equals(controllerName + "Controller", StringComparison.OrdinalIgnoreCase))
                htmlAttributes.Add("class", "current");

            return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), htmlAttributes);
        }
    }
}
使用系统;
使用System.Web.Mvc;
使用System.Web.Mvc.Html;
使用System.Web.Routing;
名称空间MyApp.Web{
公共静态类HtmlHelpers{
/// 
///返回一个锚元素(元素),该元素包含
///指定的操作。如果控制器名称与活动控制器匹配,则
///将应用css类“当前”。
/// 
公共静态MvcHtmlString MenuActionLink(此HtmlHelper帮助程序、字符串链接文本、字符串操作名、字符串控制器名){
var htmlAttributes=新的RouteValueDictionary();
字符串名称=helper.ViewContext.Controller.GetType().name;
if(name.Equals(controllerName+“Controller”,StringComparison.OrdinalIgnoreCase))
HtmlatAttributes.Add(“类”、“当前”);
返回helper.ActionLink(linkText、actionName、controllerName、new RouteValueDictionary()、htmlAttributes);
}
}
}

为了给出我自己的答案(在MVC4中测试),我从其他答案中选取了一些最好的答案,修复了一些问题,并添加了一个帮助器来处理不一定通过控制器和操作解决的URL(例如,如果您有一个处理某些页面链接的嵌入式CMS,等等)

代码也可以在github上分叉:


我想对我的布局有更多的控制,这就是我所做的

创建其他模型继承的布局模型:

public abstract class LayoutModel
{
    public CurrentPage CurrentPage { get; set; }
}
创建从ActionFilterAttribute继承的LayoutAttribute,如下所示:

<%= ActiveActionLinkHelper("Home", "Index", "Home", "selected")%>
public class LayoutAttribute : ActionFilterAttribute
{
    private CurrentPage _currentPage { get; set; }

    public LayoutAttribute(
        CurrentPage CurrentPage
    ){
        _currentPage = CurrentPage;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (result == null || result.Model == null || !(result.Model is LayoutModel)) return;

        ((LayoutModel)result.Model).CurrentPage = _currentPage;
    }
}
现在,在操作或控制器级别,我可以如下设置当前页面(如果需要,还可以设置其他内容):

[Layout(CurrentPage.Account)]
public class MyController : Controller
{

}

在我的布局视图中,我现在可以访问当前页面,以及我添加到布局模型中的任何其他内容。

使用MVC3和Razor视图提供了另一个选项:

_Layout.cshtml:

<li class="@ViewBag.NavClassHome">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@ViewBag.NavClassAbout">@Html.ActionLink("Disclaimer", "About", "Home")</li>
如果还希望为回发保留此值,则还必须在此处指定ViewBag值:

[HttpPost]
public ActionResult Index() {
    ViewBag.NavClassHome = "active";
    return View();
}

[HttpPost]
public ActionResult About() {
    ViewBag.NavClassAbout = "active";
    return View();
}
对我来说,测试和工作都很好,
[HttpPost]
public ActionResult Index() {
    ViewBag.NavClassHome = "active";
    return View();
}

[HttpPost]
public ActionResult About() {
    ViewBag.NavClassAbout = "active";
    return View();
}
@{
    ViewBag.PageName = "Index";
}
<ul>
    <li class="@(ViewContext.RouteData.Values["Controller"].ToString() == "Home" ? "active" : "")">
        <a asp-area="" asp-controller="Home" asp-action="Index"><i class="icon fa fa-home"></i><span>Home</span>
        </a>
    </li>
</ul>