How can I tell what page I am on in a ASP.NET MVC application
I'm trying 开发者_JAVA技巧to get a good idea on how to modify certain parts of the page based on what page I'm looking at. I can set certain elements with the page's controller but I'm thinking more about the global navigation menu's (currently being rendered with a RenderAction in the application's MasterPage) active states.
Like if I have some navigation links at the top of the screen (using SO's as an example)
Questions | Tags | Users | ...
If I'm in the "Questions" area or page then I want the Questions link to be active with a different color.
I don't want to have to manage this on every page and plus I don't want to be sending in values to my master page and then sending it through the RenderAction as I think that'd be messy. What I want is the Action to just know what area the rendered page is in and highlight the necessary elements.
The ViewMasterPage has a ViewContext property. The ViewContext contains the RouteData. The RouteData should have an entry for the name of the controller and current action, if they aren't the default. You could use these in your logic on the master page to determine which navigation elements to highlight.
Similarly, if you used a partial view for the navigation, you would have access to the RouteData through the ViewContext property on the ViewUserControl.
EDIT: I don't think it needs to be complicated.
<%
var current = this.ViewContext.RouteData.Values["controller"] as string ?? "home";
%>
<ul>
<li><%= Html.ActionLink( "Home", "index", "home", null, new { @class = current == "home" ? "highlight" : "" } %></li>
...
</ul>
In fact, I might even refactor it to an HTML extension to make it easier. Turns out that the helper already has a reference to the ViewContext so you don't even need to determine the current controller in the view. Note that I'm only showing one signature, you can add other signatures to handle additional route data and html attributes (these would need to be merged) as needed.
<ul>
<li><%= Html.NavLink( "Home", "index", "home" ) %></li>
...
</ul>
public static class HtmlHelperExtensions
{
public static string NavLink( this HtmlHelper helper,
string text,
string action,
string controller )
{
string current = helper.ViewContext.RouteData.Values["controller"] as string;
object attributes = null;
if (string.Equals( current, controller, StringComparison.OrdinalIgnoreCase ))
{
attributes = new { @class = "highlight" };
}
return this.ActionLink( text, action, controller, null, attributes );
}
}
Good question!
In the past I used to solve this with checking the RouteData values from the controller and action. But now i'm using the MvcContrib MenuBuilder to do this kind of job. look on their sample code to see how to work with this.
Given the following in Page.Master:
<head runat="server">
<link href="Standard.CSS" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="header" runat="server" />
</head>
<!-- and later on in the file -->
<ul>
<li>
<a href="/questions" class="question">Questions</a>
</li>
<li>
<a href="/questions" class="user">Users</a>
</li>
</ul>
Within the view Users.aspx:
<asp:Content ID="header" ContentPlaceHolderID="header" runat="server">
<title>User's Page</title>
<style type="text/css">
.user
{
background-color:yellow;
}
</style>
</asp:content>
So you don't have to do any kind of weird route parsing or hurring this or durring that. You just add a ContentPlaceHolder in your master page's header, then in each view provide some additional CSS definition within this content placeholder that makes the page look how it should for that particular view.
This is something that should be controlled from the view itself. If you don't want to modify every view, you can create an user view control (.ascx files) and add it to the master page.
精彩评论