Breadcrumb - Prevent last "crumb" from being a hyperlink?

This post has 16 replies

Top 200 Contributor
Posts: 34
web co-op Posted: Fri Apr 20, 2007 @ 10:09 AM
I'm using the sitemap control to render my site's breadcrumb trail (via a sitemap.xml file).

How can I prevent the last crumb in the trail (i.e. the current page) from being a hyperlink?

E.g.

Home > House > Kitchen > Sink

I want to prevent "Sink" from being an anchor.

Is this even possible?
Top 10 Contributor
Posts: 6,424
hwan Posted: Fri Apr 20, 2007 @ 5:34 PM
You can use templates to customize the appearance/behavior of your breadcrumbs.

eg.
	<script language="c#" runat="server">
		String LinkOrText(ComponentArt.Web.UI.SiteMapNode node)
		{
			String retVal;
			String [] arParams = HttpContext.Current.Request.RawUrl.Split('/');

			if (node.NavigateUrl == arParams[arParams.Length-1])
			{
				retVal = node.Text;
			}
			else
			{
				retVal = "<a href=\"" + node.NavigateUrl + "\">" + node.Text + "</a>";
			}

			return retVal;
		}
	</script>
	....
	<ComponentArt:SiteMap id="SiteMap1" runat="server">
		<Templates>
			<ComponentArt:NavigationCustomTemplate id="MyNodeTemplate">
				<Template>
					<%# LinkOrText((ComponentArt.Web.UI.SiteMapNode)Container.DataItem) %>
				</Template>
			</ComponentArt:NavigationCustomTemplate>
		</Templates>
	</ComponentArt:SiteMap>
Top 200 Contributor
Posts: 34
web co-op Posted: Sat Apr 21, 2007 @ 7:50 AM
Thanks hwan. I'm new to the Web.UI suite and I've not yet dabbled with templates.

I managed to achieve the result I wanted by using something like this:

breadcrumb.SelectedItem.Enabled = false;
It seems to work in all scenarios so far, but I guess yours is the proper solution. Thanks for your help!
Not Ranked
Posts: 16
chevron Posted: Tue Jul 17, 2007 @ 1:34 PM
<script language="c#" runat="server">
    String LinkOrText(ComponentArt.Web.UI.SiteMapNode node)
    {
      String retVal;
      String [] arParams = HttpContext.Current.Request.RawUrl.Split('/');

      if (node.NavigateUrl == arParams[arParams.Length-1])
      {
        retVal = node.Text;
      }
      else
      {
        retVal = "<a href=\"" + node.NavigateUrl + "\">" + node.Text + "</a>";
      }

      return retVal;
    }
  </script>
  ....
  <ComponentArt:SiteMap id="SiteMap1" runat="server">
    <Templates>
      <ComponentArt:NavigationCustomTemplate id="MyNodeTemplate">
        <Template>
          <%# LinkOrText((ComponentArt.Web.UI.SiteMapNode)Container.DataItem) %>
        </Template>
      </ComponentArt:NavigationCustomTemplate>
    </Templates>
  </ComponentArt:SiteMap>

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This solution doesn't seem to work. I have attempted to use it VERBATIM. Any thoughts?
Not Ranked
Posts: 16
chevron Posted: Tue Jul 24, 2007 @ 4:41 PM
So any thoughts on this? The code provided by ComponentArt staff does not work. Actually, how can this be done using code behind rather that in-line code and using VB.NET? ;)
Top 10 Contributor
Posts: 6,424
hwan Posted: Thu Jul 26, 2007 @ 7:58 AM
Here's a slightly modified version of what I wrote before. In this case, instead of a template I'm using the NodeDataBound server event to disable the last node.

The only caveat with this code is that it doesn't take into account the possibility for multiple parameters in the querystring, or that they could be in an unexpected order. It should give you an idea of how to make this work, however. I have tested this code with Web.UI 2007.1.
<%@ Page Language="C#" %>
<%@ Register TagPrefix="ComponentArt" Namespace="ComponentArt.Web.UI" Assembly="ComponentArt.Web.UI" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="EN">
  <head>
    <title>Customized Breadcrumbs</title>
    <link href="../../../common/baseStyle.css" type="text/css" rel="stylesheet" />    
    <link href="siteMapStyle.css" type="text/css" rel="stylesheet" />
	<script language="c#" runat="server">
		public void Page_Load()
		{
			SiteMap1.SiteMapXmlFile="siteMap.xml";
			SiteMap1.DataBind();
		}
		public void SiteMap1_OnNodeDataBound(object sender, SiteMapNodeDataBoundEventArgs e)
		{
			String [] arParams = HttpContext.Current.Request.RawUrl.Split('/');

			if (e.Node.NavigateUrl == arParams[arParams.Length-1]) 
			{
				e.Node.Enabled = false; 
			}
		}
	</script>
  </head>

  <body>

    <form id="Form1" method="post" runat="server">

    <div class="DemoArea">

    <ComponentArt:SiteMap id="SiteMap1" width="400"
      CssClass="SiteMap"     
      SiteMapLayout="Breadcrumbs"
      RootNodeCssClass="BreadcrumbsNode"
      ParentNodeCssClass="BreadcrumbsNode"
      LeafNodeCssClass="BreadcrumbsNode"
      BreadcrumbsSeparatorString=""
      DefaultImageWidth="32"
      DefaultImageHeight="16"
      ImagesBaseUrl="images/"
	  OnNodeDataBound="SiteMap1_OnNodeDataBound"
      runat="server">
    </ComponentArt:SiteMap>

    </div>

    </form>
  </body>
</html>
Not Ranked
Posts: 16
chevron Posted: Mon Aug 13, 2007 @ 2:20 PM
I have this code in my page (not using code behind). I would prefer to put the call in my master page CODE BEHIND(any thoughts on this?).

This code is not firing:
<head runat="server">
<title>Master Page</title>
<script runat="server" language="vb">
Public Sub LinkRemove(ByVal sender As Object, ByVal e As SiteMapNodeDataBoundEventArgs)
Dim arParams() As String = HttpContext.Current.Request.RawUrl.Split("/"c)

If e.Node.NavigateUrl = arParams(arParams.Length - 1) Then
e.Node.Enabled = False
End If
End Sub


</script>
</head>
...
<ComponentArt:SiteMap ID="smpTest2" runat="server"
SiteMapXmlFile="~/MasterPages/location01.xml"
BreadcrumbsLevelsToDisplay="10"
SiteMapLayout="Breadcrumbs"
CssClass="smpBreadCrumb"
LeafNodeCssClass="smpChildNodeStyle"
ChildNodeCssClass="smpChildNodeStyle"
BreadcrumbsSeparatorString="&nbsp;>&nbsp;"
ParentNodeCssClass="smpParentNodeStyle"
OnNodeDataBound="LinkRemove"
>
Top 10 Contributor
Posts: 6,149
stephen Posted: Tue Aug 14, 2007 @ 1:23 PM
You say it's not firing- how are you calling it? If you step through the function, do you have any results?
Stephen Hatcher, Developer Support Manager
Not Ranked
Posts: 16
chevron Posted: Thu Aug 16, 2007 @ 10:24 AM
I am using the control's OnNodeDataBound event to trigger the method.
Top 10 Contributor
Posts: 6,149
stephen Posted: Thu Aug 16, 2007 @ 12:08 PM
Okay- is it actually being called? If you put in breakpoint in, for example, does studio make it in?
Stephen Hatcher, Developer Support Manager
Not Ranked
Posts: 16
chevron Posted: Mon Aug 20, 2007 @ 5:36 PM
I did try that and NO. It seems to go on without throwing an exception as if it's simply ignoring the OnNodeDatabound event. Hmm....
Top 10 Contributor
Posts: 6,149
stephen Posted: Thu Aug 23, 2007 @ 1:55 PM
Now we're getting closer- can you tell me which build (major and minor) you're using, and I'll try to replicate?
Stephen Hatcher, Developer Support Manager
Not Ranked
Posts: 16
chevron Posted: Mon Aug 27, 2007 @ 12:23 PM
Here is the version number for ComponentArt.Web.UI.dll: 2007.1.1590.3
Top 10 Contributor
Posts: 6,424
hwan Posted: Wed Aug 29, 2007 @ 11:56 AM
Currently the SiteMap control only raises the NodeDataBound event if the XML file is bound on the server eg. not in the tag of the ASPX page. We are currently considering changing this behavior since it seems a little counter-intuitive.
Top 10 Contributor
Posts: 6,424
hwan Posted: Fri Aug 31, 2007 @ 7:34 AM
I looked at my code again and noticed that it doesn't account for the possibility of changed casing. To fix this, just set everything to lower.

eg.
  private void Page_Load(object sender, System.EventArgs e)
  {
    if(!Page.IsPostBack)
    {
		SiteMap1.SiteMapXmlFile="siteMap.xml";
		SiteMap1.DataBind();
	}
  }
	public void SiteMap1_OnNodeDataBound(object sender, ComponentArt.Web.UI.SiteMapNodeDataBoundEventArgs e)
	{
		String [] arParams = HttpContext.Current.Request.RawUrl.Split('/');

		if (e.Node.NavigateUrl.ToLower() == arParams[arParams.Length-1].ToLower()) 
		{
			e.Node.Enabled = false; 
		}
	}
Page 1 of 2 (17 items) 1 2 Next >