-[Danny Chen]- Blog of an ASP.NET QA tester

Tips and info about Site Navigation, ImageMap, Menu and other cool ASP.NET v2.0 features.

Binding to custom web.sitemap attributes

We've had various feature requests come in for the site navigation feature to include additional built in properties.  This got turned down because it wasn't really useful data about a Site Map Node and because it was easily done through the extensibility features.  In general this will work for any custom attribute but I'll show examples for target since it's the most commonly requested.

First, lets start with a simple web.sitemap and add a custom attributes that we'll want to map to target.  Web.sitemap allows for custom attributes to be added to each SiteMapNode.  They can be accessed later by the indexer property, for example:

Dim someNode As SiteMapNode = GetMyNode()
Dim value As String = someNode("value")
 
or
 
SiteMapNode someNode = GetMyNode();
string value = someNode["value"];

Here's an example web.sitemap:

 
<?xml version="1.0" encoding="utf-8" ?>
<
siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
  <
siteMapNode url="Home.aspx" title="Home"  target="_blank">
    <
siteMapNode url="Work.aspx" title="Work"  target="_bottom" />
    <
siteMapNode url="School.aspx" title="School"  target="_top" />
  </
siteMapNode>
</
siteMap>


Now add a menu or treeview to the page bound to the SiteMapDataSource.  In order to make this work, we'll subscribe to the Item/Node databound event.

<%@ Page Language="VB" AutoEventWireup="true"  
        
CodeFile="Default.aspx.vb"
        
Inherits="_Default" EnableViewState="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<
html xmlns="http://www.w3.org/1999/xhtml" >
<
head id="Head1" runat="server">
    <title>My Page</title>
</
head>
<
body>
    <form id="form1" runat="server">
        <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
        <asp:Menu ID="Menu1" runat="server"
        
DataSourceID="SiteMapDataSource1"      
        
OnMenuItemDataBound="Menu1_MenuItemDataBound">
        </asp:Menu>
        <asp:TreeView ID="TreeView1" runat="server"
        
DataSourceID="SiteMapDataSource1"
        
OnTreeNodeDataBound="TreeView1_TreeNodeDataBound">
        </asp:TreeView>
    </form>
</
body>
</
html>

 

And here is the code that makes it work:

Partial Class Default
    Inherits System.Web.UI.Page
    
Protected Sub TreeView1_TreeNodeDataBound(ByVal sender As Object, _
      
ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) _
      
Handles TreeView1.TreeNodeDataBound

        e.Node.Target =
CType(e.Node.DataItem, SiteMapNode)("target")
    
End Sub

    Protected Sub Menu1_MenuItemDataBound(ByVal sender As Object, _
      
ByVal e As System.Web.UI.WebControls.MenuEventArgs) _
      
Handles Menu1.MenuItemDataBound
        e.Item.Target =
CType(e.Item.DataItem, SiteMapNode)("target")
    
End Sub
End
Class

 

But what about SiteMapPath?  It's less common that this would want to be done for a SiteMapPath but that doesn't mean we shouldn't able to do it.  Lets see...  Well, it does have an itemDataBound event...

    Protected Sub SiteMapPath1_ItemDataBound(ByVal sender As Object, _
  
ByVal e As System.Web.UI.WebControls.SiteMapNodeItemEventArgs) _
  
Handles SiteMapPath1.ItemDataBound

        
If e.Item.ItemType = SiteMapNodeItemType.Parent Or _
           e.Item.ItemType = SiteMapNodeItemType.Root
Then
            If e.Item.Controls(0).GetType().ToString = _
              
"System.Web.UI.WebControls.HyperLink" Then

                CType(e.Item.Controls(0), System.Web.UI.WebControls.HyperLink).Target = _
                 e.Item.SiteMapNode(
"target")
            
End If
        End If
    End Sub

But it isn't very nice.  There are a lot of things to worry about, is the item a parent or root or is the child control actually a link.  I'm not even checking any of the other possible child controls either.  A much better way to do this would be to use the templating.  Notice the databinding against custom attributes using [key].

    <asp:SiteMapPath ID="SiteMapPath1" runat="server">
  <NodeTemplate>
    <asp:HyperLink ID="HyperLink1" runat="server"
          
Target='<%# Eval("[target]") %>'
          
NavigateUrl='<%# Eval("url") %>'
          
ToolTip='<%# Eval("description") %>'>
             <%#Eval("title")%>
    
</asp:HyperLink>
  </NodeTemplate>
</
asp:SiteMapPath>

Note: this is a bare minimum example and it would render the current node as a link as well, a <currentNodeTemplate> would further be needed to duplicate the siteMapPath behavior exactly

Comments

TrackBack said:

# March 28, 2005 11:09 PM

TrackBack said:

# March 30, 2005 4:59 PM

Hukam said:

There are not so clear about anything.

but i m trying

# April 1, 2008 8:05 AM

peter said:

Thanks Danny!  Your post saved me a lot of time. Clear and to the point.

# July 18, 2008 10:45 AM

Reenu said:

The article was briliant!! Saved me so much time!!

# September 25, 2008 10:01 AM

sun valey idaho said:

Every period detail is correct. Breaux, 39, chose Saumur\'s Combier distillery in France, with the very stills used by Pernod in the 1870s. Even the obsolete driven- in corks are accurate. And what about the psychosis? Breaux says that it\'s largely a

# October 17, 2008 12:54 AM

edcheng said:

Thank you very much!  It is working!

# October 28, 2008 5:24 AM

Peter said:

Thank you Danny.

Just what I needed to know.

# January 11, 2009 7:10 AM

SiteMapPath e Target blank | hilpers said:

Pingback from  SiteMapPath e Target blank | hilpers

# January 21, 2009 12:00 PM

Christian Abildsø said:

Thanks very much. Worked like a charm!

# July 9, 2009 5:16 AM

Karen said:

great read. I would love to follow you on twitter. By the way, did you guys know that some chinese hacker had hacked twitter yesterday again.

# January 18, 2010 1:31 PM

Driving school knowledge tests said:

Thanks for sharing the codes. That was pretty great! Love it. Cheers for more! :D

# February 23, 2010 2:49 AM

kikus said:

отлично сделано, интеретсно читать 98)

# June 13, 2010 7:00 AM

prareptissere said:

All pizza places of USA pizza-us.com/.../90035

Find your best pizza.

# September 1, 2010 1:00 PM

TypeTalaneria said:

The restaurants list with thousands of restaurants reviewed by visitors. restaurants-us.com/.../33618

# September 30, 2010 2:52 PM

ChetteEresy said:

Directory of restaurants organized by states   <a href="restaurants-us.com/.../">Memphis Championship Barbecue</a>

# January 24, 2011 3:50 AM

ChetteEresy said:

Overview of US restaurants.  <a href="restaurants-us.com/.../">La Perla Del Pacisico</a>

# January 31, 2011 4:03 AM

Pizza said:

Neapolitans earned the right to claim pizza as their own by inserting a tomato into the equation.

Neapolitans earned the right to claim pizza as their own by inserting a tomato into the equation.

# March 10, 2011 5:17 PM

Alcazzarre said:

Maybe Alcazzarre could help you to solve your problems? You'r welcome pal.

# March 16, 2011 11:08 AM

Home Security Monitoring said:

Good web site! I really love how it is simple on my eyes and the data are well written. I am wondering how I might be notified when a new post has been made. I have subscribed to your RSS feed which must do the trick! Have a nice day!

<b><a href="www.blogsstart.com/.../how-can-you-keep-your-home-security-system.html

">Home Security Monitoring service

<a/><b/>

# March 30, 2011 9:29 AM

ReageasencyuI said:

Что для Вас Юмор?    

<a href=http://xn--c1aeb8eua.xn--p1ai/>конвертеры видео в формат mpeg4 mp4</a>

# January 31, 2012 4:12 AM

ReageasencyuI said:

Что для Вас Юмор?    

<a href=http://xn--c1aeb8eua.xn--p1ai/>картинки на тему потеря времени</a>

# January 31, 2012 5:12 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)