ASP.NET Custom Navigation in Master Page
All,
I am trying to decide the best way to convert my current asp.net page into a master page. This issue I have is with the navigation. I have 3 aspx pages which are essentially html with nothing flash in as yet. These are:
- Home
- Reports
- Admin
In my current pages, the menu built using static html as follows:
<div id="nav">
<ul>
<li><a href="Default.aspx" class="tab-unselected" title="Home">Home</a></li>
<li><a href="reports.aspx" class="tab-unselected" title="Reports">Reports</a></li>
<li><a href="administration.aspx" class="tab-selected" title="Admin">Admin</a>
</li>
</ul>
</div>
The class for each li a class is currently determined in the actual html source. So in Default.aspx the class for li a href="Default.aspx" ... would point to the selected tab class in my css, tab-selected. The other classes for the rest of li a's would be tab-unselected.
Again in reports.aspx, the class for li a href="reports.aspx" ... would point to the selected tab class in my css, tab-selected. The other classes for the rest of li a's would be tab-unselected.
My CSS is displaying the menus perfectly with the above.
I then thought I would try moving to Master pages. So I copied the above into th开发者_StackOverflow中文版e master page. This looks ok but the problem is as the navigation is in the Master page, how can I change the highlight the current page in the navigation.
Then I thought I would try and use the control and put the above navigation items in it. When I ran the navigation was rendered as a table and so completely broke my css. I thought tables were bad in terms of laying out things like menus and you should use unordered lists?
Question is, what is the best way to implement my navigation with ASP.NET?
Thanks
Andez
If you want to use your html list to display your navigation but style your list items using CSS then you could use this technique.
Use inline code blocks such as (assuming VB)
<% If Page.Request.Path.Contains("Default.aspx") Then %>
<li class="selected">
<% Else %>
<li>
<%End If%>
<a href="Default.aspx" class="tab-unselected" title="Home">Home</a></li>
You would need an IF statement for each page and the code will look a bit scrappy. I'm not saying it's the best way but basically if you are using a single piece of html for you menu (but it in the Masterpage or a Control) you will need to use some logic code somewhere for the html to be different on each page. You could do this in the code-behind as well but adding some inline code blocks is the perhaps the easiest/quickest way. You could get more funky and write a helper class that wraps it all up in a select statement and just call
MenuHelper.RenderLink("Default.aspx")
but that will take more work - give me a shout if fancy trying this approach instead.
As for why your tables broke I don't know. My opinion would be if you want to use tables and your site/users won't suffer from it then go ahead - but if you have to consider mobile devices and screen readers etc then it is my understanding that tables will be harder to navigate. It's really up to you!
Cheers
Came across the following link:
http://forums.asp.net/t/1626206.aspx
Version 4.0 of the .NET Framework has some nice changes to the asp:Menu control. One of them is to render as a list. Yay! So for now I have moved from VS2008 to VS2010 Express.
After a little fiddling around I am now using a site map with an asp:Menu within a Master page as follows:
Web.sitemap
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="" title="" description="">
<siteMapNode url="Default.aspx" title="Home" description="" />
<siteMapNode url="reports.aspx" title="Reports" description="" />
<siteMapNode url="administration.aspx" title="Administration" description="" />
<siteMapNode url="ChildPage.aspx" title="Master Template" description="" />
</siteMapNode>
</siteMap>
Site.master
...
<head runat="server">
<link rel="stylesheet" type="text/css" href="styles/mystyle.css" />
</head>
<body>
<form id="Form1" runat="server">
<div id="header">
<div id="nav">
<asp:SiteMapDataSource id="nav1" runat="server" />
<asp:Menu ID="main-menu" runat="server" DataSourceID="nav1"
Orientation="Horizontal" StaticSelectedStyle-CssClass="tab-selected"
CssClass="nav"
StaticDisplayLevels="2" IncludeStyleBlock="False" RenderingMode="List" >
</asp:Menu>
</div>
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</form>
</body>
The thing with the Site Map is that you are required to have 1 top level siteMapNode which I leave as empty. StaticDisplayLevels is set to 2 in the asp:Menu, so the list is rendered as follows:
<ul class="level1">
<li><a></a></li>
<li><a class="level2 selected" href="/Web%20Portal/Default.aspx">Home</a></li>
<li><a class="level2" href="/Web%20Portal/reports.aspx">Reports</a></li>
<li><a class="level2" href="/Web%20Portal/administration.aspx">Administration</a></li>
<li><a class="level2" href="/Web%20Portal/ChildPage.aspx">Master Template</a></li>
</ul>
As you can see it puts the top level siteMapNode as the first item in the list. Which I do not want. To work around this I hide the element using the following CSS.
#nav li:first-child a
{
display: none;
}
Everything is now looking nice and very similar to the static html pages.
Andez
May be the solution I am trying to provide is not optimized but worked for me.
In the static HTML Menu in the Master page, have all the "li" tag with the ID as of the Page Name.
<ul>
<li ID="home"><a href="home.aspx">Home</li>
<li ID="About"><a href="about.aspx">About</li>
<ul>
Then in the Master Page use JQuery to get the Page Name. Some thing like
$(function () {
var filePath = window.location.pathname;
var fileName = filePath.substr(filePath.lastIndexOf("/") + 1);
var name = fileName.split('.');
var page_name = name[0];
$('#' + page_name).addClass("active"); // Add the CSS class which sets the active Menu
});
In CSS do something like
.active { background=#000; color=#fff; }
I hope this helps..
精彩评论