The task was simple enough: add a menu item to my company web site for my blog . As you might have discerned, I use WordPress.com to manage and host my blog. All I wanted to do was make the blog accessible to my web site visitors. This called for a Blog menu item on my site, which when clicked, would open the blog site in a new window.
Like many ASP.NET web sites, I use a SiteMapDataSource in conjunction with a TreeView control to provide the menus. The SiteMapDataSource looks for a file in the virtual root called Web.Sitemap. This file is a relatively simple XML file with a series of siteMapNode tags, which can be nested to provide a hierarchy of menu items. Here is an abbreviated version of my Web.sitemap file:
<siteMap xmlns=”http://schemas.microsoft.com/AspNet/SiteMap-File-1.0” >
<siteMapNode url=”root” title=”root” description=””>
<siteMapNode url=”Home.aspx” title=”Home” description=”Home page”/>
<siteMapNode url=”Services.aspx?topic=services” title=”Services”>
title=”ASP.NET Web Apps”/>
title=”Fast Online Data Entry”/>
title=”Microsoft SQL Server”/>
<siteMapNode url=”Resources.aspx” title=”Resources”/>
<siteMapNode url=”About.aspx” title=”About Us”/>
Notice that each node has a url attribute, which specifies where to navigate to for this menu item, and a title attribute, which is the text displayed in the menu.
So far, so good. Here is the code in the master page declaration (MasterPage.master) to put this menu in place:
<asp:TreeView ID=”tvNavbar” runat=”server”
Notice that the ShowStartingNode attribute of the SiteMapDataSource is set false to suppress the root level of the menu hierarchy.
I have also set several of the attributes of the TreeView to specify the look and feel, such as BackColor, BorderStyle, CssClass (which references a style class in the site CSS file), Orientation, and so on. Crucially, the DataSourceID points to the SiteMapDataSource.
So back to my original goal of opening the blog entry in a new window. The typical entry in the sitemap file implements a normal menu item which navigates to a page in the site:
<siteMapNode url="Services.aspx?topic=services" title="Services">
The typical way to open a link in a new window is to include the target attribute, as for example in this anchor tag:
<a href="https://danhurwitz.wordpress.com" target="_blank">Blog</a>
So translating this to the sitemap file, you would expect something like this to work:
<siteMapNode url="https://danhurwitz.wordpress.com" Title="Blog" target="_blank"/>
However, when I put this into the sitemap file, the target attribute had zero effect: the page opened in the current window. So a different approach was needed.
Hence the need for the OnTreeNodeDataBound attribute. This event is raised every time a new node is bound to the TreeView. But to make this work , I need some sort of flag in the node to tell the event handler code to add the Target attribute. So I put a hash mark (#) in the url of the siteMapNode, and remove the target attribute:
<siteMapNode url=https://danhurwitz.wordpress.com/# Title="Blog"/>
Then in the event handler, I test for the presence of the hash mark, and if it is found, add the target attribute.
protected void tvNavbar_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
e.Node.Target = "_blank";