How to Implement "if active" detection in an Html.Helper?
Apologies, I'm new to ASP.NET MVC. :)
I'm unsure if this is simple a misunderstanding, or incorrect paradigm to use for this kind of functionality, but this is what I've come up with so far...
I wish to provide the common functionality adding a css attribute (in this case "active") to an anchor tag, when we detect that the user is on the same page as its href. In the context of MVC (and specifically for my application) I am interpreting this as "When the current active Controller is the same as the hyper-link's target location."
Okay! So. Where am I with the code?
I've implemented the following Html helper extension to aid in creating the slightly "tweaked" from standard links that I require.
public static MvcHtmlString ActiveActionLink (this HtmlHelper helper, string labelText, string action, string controller)
{
var cssProprties = controller + " active";
return helper.ActionLink(labelText, action, controller, null, new { @class = cssProprties });
}
At present you can see that I am applying two css classes. The first is the name of the controller, this is fine. The later, I have no logic I simply add the active css-class. This is what I've been trying to add the logic to.
My theory, is all that I need to do is dig into the correct object to locate what controller I'm currently within, and match that to the "controller" parameter that is passed in. If these match, add the active class.
So, in two questions...
Is this the correct/an acceptable way of "thinking" in ASP.NET mvc?
If so: which objects can I dig through, from the level that I am at, to access the information for comparison - that I require?
UPDATE:
After what normally happens when I write a question on SO, I've had a brainwave. I noticed a nugget of code in the BeginForm helper that lead me to create this example:
public static MvcHtmlString ActiveActionLink (this HtmlHelper helper, string labelText, string action, string controller)
{
var cssProprties = controller;
// if this controller is the target controller, page is active.
if (helper.ViewContext.RouteData.Values["controller"].ToString() == controller)
cssProprties += " active";
return helper.ActionLink(labelText, action, controller, null, new { @class = cssProprties });
}
So I guess this answers the "which objects can I dig through?" question. Also as this was directly i开发者_StackOverflownfluenced by the source of MVC - presumably the "Is this the correct/an acceptable way of "thinking" in ASP.NET mvc?" question too?
This seems about the right sort of approach though there are a few things you will need to consider taking account of.
If the link is rendered via Html.Action or Html.RenderAction then the ViewContext will refer to the controller that child action is on, which may or may not be what you want. If you want it to refer to the controller of the main page you might also want to do a recursive check on ViewContext.ParentActionViewContext (keep calling parent until it is null then get the controller).
Secondly,there are areas, you can have controllers with the same name if they are in different areas so I'd recommend a second helper that takes an area string and checks on both that and the controller.
This is the code that I've decided to settle on. It solves the Issue I was experiencing & was directly influenced from the source-code of asp.net mvc2. I hope it helps others too.
public static MvcHtmlString ActiveActionLink (this HtmlHelper helper, string labelText, string action, string controller)
{
var cssProprties = controller;
// if this controller is the target controller, page is active.
if (helper.ViewContext.RouteData.Values["controller"].ToString() == controller)
cssProprties += " active";
return helper.ActionLink(labelText, action, controller, null, new { @class = cssProprties });
}
精彩评论