in

ASP.NET Weblogs

-[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.

I wrote a custom provider and now autoselecting nodes in Menu and TreeView doesn't work?

Here's a question I get quite often.  The problem: Menu and TreeView won't autoselect the current node as you're navigating around the site.  It usually happens two ways.  First: someone decided to bind the Menu or TreeView through DataSource instead of DataSourceID or Second: Someone wrote a custom SiteMapProvider.  So what's happening?

Actually, there are two problems here.  In order for Menu/TreeView (here on lets just pretend it's for Menu since the code in TreeView is identical for all intensive purposes and this post applies to both equally) to autoselect a node it must satisfy two conditions: 

   1) Must be bound to a SiteMapDataSource through DataSourceID
   2) The url of the Current Node has to match the key of the item

Ok, so that 2nd one is really an oversight on our part (and should eventually get fixed) but it's important to know about it so that we can make sites work Today.  It so happens that XmlSiteMapProvider found it useful to set the key to the url so this problem is avoided.  Do we recommend it as a best practice?  Not necessarily, if your data comes from a Sql DB, for example, you might have an identity field that would be better suited for the key.

So what can you do?  
For Problem #1) Why are you using DataSource instead of DataSourceID for a SiteMapDataSource?  Add the DataSource to the page, give it an ID and use DataSourceID (and you can still do this all in code)
For problem #2) You could adjust your provider to mate the key and url and store whatever data was in Key in a custom attribute.
(what do you do if there is no url? come up with something unique, XmlSiteMapProvider uses a GUID)


And, if you really don't want to do either of these, then you can also write custom databinding code like this:

C#:
    private string currentKey = SiteMap.CurrentNode.Key;
    protected void Menu1_MenuItemDataBound(object sender, MenuEventArgs e)
    {
       
        if( string.Equals(e.Item.DataPath, currentKey, StringComparison.OrdinalIgnoreCase ) )
            e.Item.Selected = true;
    }

VB:
    Protected Sub Menu1_MenuItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MenuEventArgs)
        Static currentKey As String = SiteMap.CurrentNode.Key
        If String.Equals(e.Item.DataPath, currentKey, StringComparison.OrdinalIgnoreCase) Then
            e.Item.Selected = True
        End If
    End Sub

 

Comments

 

Hannes said:

Thanks for the solution to #2, I would never have found that on my own...

I had a similar problem with not knowing that my implementation of certain methods such us GetChildNodes needs to also perform security trimming even when IsAccessibleToUser is implemented.

It was really annoying to not have the details of which methods and which overloads of those need to be implemented for something to work when implementing a custom SiteMapProvider.

It just seems that the interface to the SiteMapProvider is flawed by design.

September 28, 2007 6:05 AM

Leave a Comment

(required)  
(optional)
(required)  
Add