Creating a custom Bread Crumb control in asp.net
Hi,
We all might be aware of the bread crumbs shown
on so many websites. Bread crumbs help users in a big way to
navigate the website in a structured manner. Asp.net
provides a very good sitemap control which can be used to
display a bread crumb. This uses a sitemap file which is
actually a xml file indicating the struture and hierarchy of
your web site.
A few days ago a colleage of
mine ran into soem issues with the standard asp.net sitemap
control. It became evident that managing and keeping track
of query string was not easy in the standard sitemap
control.
This motivated me to develop a
custom bread crumb control. The control i developed was a
pretty simple one. I will discuss about this control
and explain in detail about the code.
Some of the
features of this bread crumb control are -
1. It
keeps track of the query string of previous pages
browsed.
2. It doesnt require any xml file.
This is a very simple control and as you can see
it can be developed further. The asp.net sitemap control is
superior to it in a lot of ways and i will recommend users
to use it unless you need new features.
The
breadcrumb consists of two main classes. - BreadCrumbNode
and BreadCrumb
BreadCrumbNode represents a
visited URL or the current page, in addition it contains
information like the caption/title to be shown on the
breadcrumb. You can modify the class to include more
information.
The other class is the
BreadCrumb which represents the BreadCrumb Control. Below is
the code for both the classes -
namespace
Web.Custom.Controls
{
using System;
using System.Data;
using
System.Configuration;
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;
/// <summary>
/// Summary description for
BreadCrumbNode
/// </summary>
///
public class BreadCrumbNode
{
private String strTitle = string.Empty;
private
string strURL = string.Empty;
public
BreadCrumbNode(String strTitle)
{
this.strTitle = strTitle;
strURL =
HttpContext.Current.Request.Url.AbsoluteUri; //picks up the
current url along with the query string
}
public string Title
{
get
{
return
strTitle;
}
}
public string URL
{
get
{
return
strURL;
}
}
}
}
namespace
Web.Custom.Controls
{
using System;
using System.Data;
using System.Configuration;
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;
using
System.ComponentModel;
/// <summary>
/// Summary description for BreadCrumb
///
</summary>
public class BreadCrumb : WebControl
{
public BreadCrumb()
{
}
/*The below property stores the lastvisted urls
(represented by the class BreadCrumbNode) in a stack.
This stack is then stored in the session.
The
strURLGroup is required in case ur site has multiple
different sections or to be more clear multiple hierarchies
with each having a different root/home page
*/
private Stack<BreadCrumbNode>
URLList
{
get
{
if
(HttpContext.Current.Session["KEY_" + strURLGroup] ==
null)
{
HttpContext.Current.Session["KEY_" + strURLGroup] = new
Stack<BreadCrumbNode>();
}
return (Stack<BreadCrumbNode>)HttpContext.Current.Session["KEY_" + strURLGroup];
}
set
{
HttpContext.Current.Session["KEY_" + strURLGroup] =
value;
}
}
/* This function may be required to be called
from each individual page. */
public
void Add(BreadCrumbNode bcn)
{
/* search if this page already exists. If it
exists then remove it and also all other pages after it.
This is like i am going to the parent page from a child
page */
BreadCrumbNode[] bcnArr =
URLList.ToArray();
bool nodeExists =
false;
for (int cnt = 0; cnt <
bcnArr.Length; cnt++)
{
if (bcn.Title.Equals(bcnArr[cnt].Title))
nodeExists = true;
}
//if the page exists then remove the nodes
after it
if (nodeExists)
{
BreadCrumbNode bcnTemp = null;
do
{
bcnTemp =
URLList.Pop();
} while
(!bcnTemp.Title.Equals(bcn.Title));
}
URLList.Push(bcn); //push in the current node
}
public void Add(string strTitle)
{
Add(new BreadCrumbNode(strTitle));
}
//The levels function represent
the level of the hierarchy at which a page is
// It
may be required that a page calls the level function
corresponding to the level it is in the hierarchy
//Like
a home page will call level0, a level1 page will call level1
and child may call level2
//This is not required but
to maintan stack in a consistent state even when the user
skips the strutured navigation
//of a wesite that
may happen by directly typing in the url in place of using
the menu links
public void Level0()
{
URLList.Clear();//clear all the nodes
as this is the root/home page
}
public void Level1()
{
BreadCrumbNode[] bcnArr = URLList.ToArray();
if (bcnArr.Length > 0)
{
URLList.Clear();
URLList.Push(bcnArr[bcnArr.Length - 1]);
}// leave the home page alone
}
public void Level2()
{
BreadCrumbNode[] bcnArr = URLList.ToArray();
if (bcnArr.Length > 1)
{
URLList.Clear();
URLList.Push(bcnArr[bcnArr.Length - 1]);
URLList.Push(bcnArr[bcnArr.Length - 2]);
}
}
//finally render the links
according to the data in teh stack
protected
override void Render(HtmlTextWriter writer)
{
// base.Render(writer);
BreadCrumbNode[] bcnArr = URLList.ToArray();
if (bcnArr.Length > 0)
{
for (int cnt = bcnArr.Length -1 ; cnt > 0; cnt--)
{
writer.Write("<A href=\"");
writer.Write(bcnArr[cnt].URL);
writer.Write("\">");
writer.Write(bcnArr[cnt].Title);
writer.Write("</A>");
writer.Write(" | ");
}
writer.Write("<B>");
writer.Write(bcnArr[0].Title);
writer.Write("</B>");
}
}
private String strURLGroup = "";
}
}
The usage of the above classes is shown
aspx side
<%@ Register
Namespace="Web.Custom.Controls" TagPrefix="bc" %>
in
the body section
<bc:BreadCrumb runat="server"
ID="bc1" />
codebehind file
protected void Page_Load(object sender, EventArgs e)
{
bc1.Level0();
bc1.Add("Home");
}
for the child of the
above page aspx remains the same
protected void
Page_Load(object sender, EventArgs e)
{
bc1.Level1();
bc1.Add("section1");//this can be
the caption you want like section2
}
the output will be
Home | Section1
or
Home
| Section2
as per the value of teh parameter in the
bc1.Add function
for page that is after the
section1 page
protected void Page_Load(object
sender, EventArgs e)
{
bc1.Level2();
bc1.Add("Child");//this can be
the caption you want like section2
}
The
output will be
Home | Section1 | Child
I
hope i have been clear enough for you to understand the code
and the concept. I have attached the zip file that contains
the code and a simple demo - BreadCrumb.zip.
I help this post of mine will help to put in motion more ideas related to this. In case it does, do let me know.
Cheers
Sohail Sayed