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?

Was it helpful?

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'.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top