Opening a New Window from a TreeView Menu Item

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:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<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”>
   <siteMapNode url=”Services.aspx?topic=projects”
title=”.NET Applications”>
     <siteMapNode url=”Services.aspx?topic=webapps”
title=”ASP.NET Web Apps”/>
     <siteMapNode url=”Services.aspx?topic=folde”
title=”Fast Online Data Entry”/>
   </siteMapNode>
   <siteMapNode url=”Services.aspx?topic=database”
title=”Microsoft SQL Server”/>
  </siteMapNode>
   <siteMapNode url=”Resources.aspx” title=”Resources”/>
  <siteMapNode url=”About.aspx” title=”About Us”/>
 </siteMapNode>
</siteMap>

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:SiteMapDataSource ID=”smds” runat=”server”
               ShowStartingNode=”false” />
<asp:TreeView ID=”tvNavbar” runat=”server”
   BackColor=”Transparent”
   BorderStyle=”None” CssClass=”TextMenu”
   DataSourceID=”smds”
   NodeIndent=”25″ Width=”200″
   NodeWrap=”false” NodeStyle-VerticalPadding=”10″
   Orientation=”Vertical”
   OnTreeNodeDataBound=”tvNavbar_TreeNodeDataBound”
   SelectedNodeStyle-CssClass=”TextMenuSelected”
   StaticDisplayLevels=”2″>
</asp:TreeView>

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)
{
   if (e.Node.NavigateUrl.Contains("#"))
      e.Node.Target = "_blank";
}

Works great!

Advertisements

About Dan Hurwitz

A consultant specializing in .NET.
This entry was posted in Software Development and tagged , , , , , , , , , , . Bookmark the permalink.

3 Responses to Opening a New Window from a TreeView Menu Item

  1. Dan Hurwitz says:

    Well this is embarrasing, replying to my own post to point out a bug. This code does work as advertised when I run it inside Visual Studio. However, I was mortified to find that the deployed version opens a new window for every item on the side menu, not just the Blog menu item.

  2. Dan Hurwitz says:

    That bug is now fixed. Turns out it was just a version mismatch between my dev system and the published web site. This illustrates the problems that await when you take “shortcuts” and make changes directly on the production site. No matter how simple the changes might seem, it is always best to make them in Dev, perform proper testing, and follow the standard deployment protocol. This is something I unfailingly do for client projects, but sometimes skimp on my own stuff. The shoemaker’s son, and all that.

  3. i love your blog, i have it in my rss reader and always like new things coming up from it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s