Programmatic solution to change navigation id to highlight current page ASP.NET
-
06-07-2019 - |
Question
I am writing a website with Visual Studio 2008 and ASP.NET 3.5. I have a masterpage set up to simplify the layout and to keep the content pages for content rather than content and layout.
The navigation is list, css'd so it looks like a bar. In order to highlight the page on the bar, the list item needs to look like this <li id="current">
. I do not want to use <asp:ContentPlaceHolder>
if I can avoid it. Is there some code I can add to each of my pages (or just to the masterpage?) to accomplish this or am I stuck using <asp:ContentPlaceHolder>
's?
Solution
Add a property to your master page called Page Section
public string PageSection { get; set; }
Add a MasterType page directive to the top of your content pages
<%@ MasterType VirtualPath="~/foo.master" %>
In your content page code behind, set the PageSection property of the master page
Master.PageSection = "home";
In your master page, make the body tag a server tag
<body ID="bodyTag" runat="server">
In the master page code behind, use that property to set a class on the body tag
bodyTag.Attributes.Add("class", this.PageSection);
Give each of your nav items a unique ID attribute.
In your css, change the display of the nav items based on the current page class
.home #homeNavItem,
.contact #contactNavItem
{
color: #f00;
}
OTHER TIPS
Have you considered using a Web.sitemap file? It makes it real easy. If your sitemap file looks like this...
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode>
<siteMapNode url="~/Default.aspx" title="Home" description="" />
<siteMapNode url="~/Blog.aspx" title="Blog" description="" />
<siteMapNode url="~/AboutUs.aspx" title="AboutUs" description="" />
</siteMapNode>
</siteMap>
...then you can do this in your master page to achieve the results you want:
<asp:SiteMapDataSource ID="sitemapdata" runat="server" ShowStartingNode="false" />
<ul id="navigation">
<asp:Repeater runat="server" ID="navrepeater" DataSourceID="sitemapdata">
<ItemTemplate>
<li class="<%# SiteMap.CurrentNode.Equals(Container.DataItem) ? "activenav" : "inactivenav" %>"><a href="<%# DataBinder.Eval(Container.DataItem, "url") %>"><%# DataBinder.Eval(Container.DataItem, "title") %></a></li>
</ItemTemplate>
</asp:Repeater>
</ul>
The current page's LI will have a class of "activenav" (or whatever you decide to use), and the others will have a class of "inactivenav". You can write your CSS accordingly. This is the technique I use on my site and it works great.
It's a better semantic match and likely an easier variable to set to keep the navigation using the same classes or ids everywhere and only alter the body element's id to match:
<li id="homeNav">home</li>
<li id="blogNav">blog</li>
and then on each page...
<body id="home">
<body id="blog">
And in the css:
#home #homeNav {background-image:url(homeNav-on.jpg);}
#blog #blogNav {background-image:url(blogNav-on.jpg);}
The use or non use of ContentPlaceHolder will not affect which element has the id="current" set on it.
You will have to look at some method, either in your codebehind for the master page, a javascript function or something else when rendering the menu component to properly add the id="current" to the list when it is created.
How about creating a protected string property in your masterpage code class? Override the OnLoad:
protected string _bodyId;
protected override void OnLoad(EventArgs e)
{
_bodyId = "your css id name";
}
Then in your masterpage aspx:
<body id="<%= _bodyId %>">
Then you don't have to mess with your CSS, especially useful if the CSS came from a design agency.
Here's how we've achieved it using JQuery by appending the css class to change the background.
$("ul.nav > li > a:contains('<%= SiteMap.CurrentNode.ParentNode.Title %>')").addClass("navselected");
The ".nav
" in ul.nav
(in Jquery) is the css class applied to the UL tag.
:contains
helps checking the contents of all "a" tag/element within the ul->li->a with ParentNode Title that is printed in Menu...
If found, applies the css class named navselected to the specific ul->li->a tag/element.
Regards, Minesh Shah
Systems Plus Pvt. Ltd.
www.systems-plus.com
I would use javascript to accomplish this. In css, change your #current to be a class (.current) and then have id's on each of your ListItems that you create. Then using RegisterStartupScript, call a javascript method that gets the appropriate ListItem and assigns it a style of current. Using Prototype, this would look like $('MyPageLi').className = 'current'.