A Semi-Dynamic Sitemap Solution
12 Jan 2008I was creating a website which had pages with multiple views. I wanted a fairly simple sitemap solution, without creating any custom sitemap provider, which could show the current view name in the breadcrumb trail like this -
Home » Parent Page » Current Page » Current View 1
Home » Parent Page » Current Page » Current View 2
So here’s what I did to achieve that -
MasterPage.Master:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>CMS ::</title> </head> <body> <form id="form1" runat="server"> <div> <asp:SiteMapPath ID="SiteMapPath1" runat="server" OnPreRender="SiteMapPath1_PreRender" PathSeparator=" : " RenderCurrentNodeAsLink="True"> </asp:SiteMapPath> </div> <div> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </div> </form> </body> </html>
MasterPage.master.cs:
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Collections.Generic; public partial class MasterPage : System.Web.UI.MasterPage { private string _currentViewName = string.Empty; public string CurrentViewName { get { return _currentViewName; } set { _currentViewName = value; } } protected void Page_Load(object sender, EventArgs e) { SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(SiteMap_SiteMapResolve); } protected void SiteMapPath1_PreRender(object sender, EventArgs e) { //If there is a current view name defined then add a child node to the breadcrumb trail. if (!string.IsNullOrEmpty(CurrentViewName)) { SiteMapNodeItem sepItem = new SiteMapNodeItem(-1, SiteMapNodeItemType.PathSeparator); ITemplate sepTemplate = SiteMapPath1.PathSeparatorTemplate; if (sepTemplate == null) { Literal separator = new Literal(); separator.Text = SiteMapPath1.PathSeparator; sepItem.Controls.Add(separator); } else { sepTemplate.InstantiateIn(sepItem); } sepItem.ApplyStyle(SiteMapPath1.PathSeparatorStyle); SiteMapNodeItem viewItem = new SiteMapNodeItem(-1, SiteMapNodeItemType.Current); Literal viewName = new Literal(); viewName.Text = CurrentViewName; viewItem.Controls.Add(viewName); viewItem.ApplyStyle(SiteMapPath1.CurrentNodeStyle); SiteMapPath1.Controls.AddAt(-1, sepItem); SiteMapPath1.Controls.AddAt(-1, viewItem); } else //...if not then don't show the current node as a link. { SiteMapPath mySMP = (SiteMapPath)sender; mySMP.RenderCurrentNodeAsLink = false; mySMP.DataBind(); } } private SiteMapNode SiteMap_SiteMapResolve(Object sender, SiteMapResolveEventArgs e) { SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true); //If there is a current view defined then set the URLs in the breadcrumb trail //so that they point to the correct view. For example: //Home (Home.aspx) > News (News.aspx?View=0) > Edit (News.aspx?View=1) if (!string.IsNullOrEmpty(CurrentViewName)) { string currentRequest = e.Context.Request.UrlReferrer.PathAndQuery; if (currentNode != null) currentNode.Url = currentRequest; } return currentNode; } }
Now you are all set. To put this code in action, just declare a curent view name like this in your pages wherever needed:
((MasterPage)this.Master).CurrentViewName = "News Listing";
This solution was inspired by this blog post.