The out of the box navigation controls work for many scenarios, but what happens if they don't? What are the options available to have custom navigation in SharePoint (WSS or MOSS)? I am not just talking about look and feel, in fact I am mostly talking about functionality and controlling the HTML output that the navigation renders e.g. you want HTML DIV tags instead of tables with rows and cells, or what about UL and LI tags?
This is something that I have been meaning to write about for some time now, but have never had the chance. I have had so many folk ask how to have more control over the navigation output and so at long last I have decided to document several options. Besides the HTML output control, I have also had scenarios like "the navigation works okay, but in certain scenarios I want it to also wash the dishes, but only if the navigation node is a dishwasher". In this post you will find information on how to solve both of these types of scenarios, and therefore I cover the following options:
This scenario doesn't solve either the issues described earlier, but I just wanted to make sure you were up to speed on navigation in SharePoint before you head down any of the other options. In other words....read this option for background info!
The navigation you see below was done using the out of the box ASP Tree View control with custom CSS styles. Not bad result for no code! In other words, no code development, just standard styling "stuff" in SharePoint.
I am not going to cover how this was achieved and all the various configuration options, but do recommend you read the following posts which do
Out of the box configuration options and how navigation works:
Branding the out of the box navigation:
Here you provide CSS styles for the SharePoint ASP menu control, the ASP .NET menu or ASP .NET tree controls, depending on which one of those you are using. (as a side note, the SharePoint ASP menu control inherits from the ASP .NET menu control to change some small behaviour).
You may find that purchasing a 3rd party navigation control will be a better option for you if you are looking for a "fancy" or WOW user experience, without having to worry about developing or supporting it yourself. What you are really looking for here is a control which can be used to bind to an ASP .NET navigation data source provider, like the ASP .NET menu, ASP .NET tree and SharePoint ASP menu controls do. In other words, you want it to work just like they do, and simply replace one of the out of the box controls with a 3rd party one.
One such company that provides rich controls is Telerik.
The above screen shot is their RadMenu control (showing various style options). They even have documentation on how to get this control working in SharePoint.
The out of the box navigation controls emit HTML which is full of tables, rows and cells. In some scenarios customers have requested that instead of HTML tables, they would like to have DIV tags (or any other set of HTML tags). One way of achieving this is through the CSS Control Toolkit. The toolkit consists of control adapters, which are little pieces of logic that you add to your web site to effectively "adapt" an ASP.NET control to render the HTML you prefer. The ASP.NET 2.0 CSS Friendly Control Adapters kit provides pre-built control adapters that you can easily use to generate CSS friendly markup from some of the more commonly used ASP.NET controls.
This will work with ASP navigation and SharePoint navigation controls. Instead of me documenting the steps to get this working in a SharePoint environment, let me rather point you to a blog entry by the Mossman titled "CSS Friendly Control Adapters in SharePoint 2007 (A Walk-Through)", which has the steps documented for you already.
NOTE: when I tried this for demonstration purposes it worked well, except for the fact that it also changed the navigation on the internal SharePoint application pages e.g. site settings etc, and this caused weird behaviour on those pages. Therefore, you might want to modify the source code of the CSS Control Adapter for the menu control to only work on specific scenarios so that it doesn't effect your application pages. The source code for the toolkit is available on CodePlex.
You develop a custom ASP .NET navigation control which inherits from an existing control i.e. ASP .NET menu, ASP .NET tree or SharePoint ASP menu control. You then have the option of overriding specific functionality to get what you want (for formatting and perhaps functionality reasons). This is exactly what the SharePoint product team did when developing the SharePoint ASP menu, it inherits from ASP .NET menu and changes certain functionality. A good example of how to do this, is found by downloading the source code for the SharePoint ASP menu which the SharePoint team have released here.
NOTE: you may not be able to override all functionality, you will need to play with this to see if you can achieve your goals, otherwise you will need to use one of the other custom navigation options.
The next 2 options cover the scenario where you want to control the HTML output whether it be DIV, Table or any another HTML tags. It also covers the dishwasher scenario I mentioned at the top of this article. In the dishwasher scenario you want custom logic in deciding which nodes to render in your navigation, beyond the standard SharePoint logic and rules e.g. only render navigation nodes where the 1st letter of the node, is the same as the first letter of the name of the person viewing the page. Okay, not a great real world example, but hopefully you get the idea.
In this option (option 5), you develop a navigation control in the same way as you develop any other ASP .Net server control, but you call the SharePoint API to get back the navigation nodes required to render your navigation.
You may have some type of recursive function which starts from the current node (current site e.g. SPWeb object) and loops through all child and sibling nodes to render the navigation. Those developers who come from a Microsoft Content Management Server (MCMS) 2002 background will understand this model, because this is essentially the same as looping through channel and posting objects to render the navigation required.
Note: The out of the box navigation controls in SharePoint do not work in this way, they are true ASP .NET navigation controls which get there data (navigation nodes) from a data source control.
Developing a control which does not need a data source control has some draw backs. You need to code various configuration options into your control if you want SharePoint configuration to still be used to define which nodes are rendered e.g. show pages or not, start from the current node, ignore headings, ignore links. I.e. the options which are available through the SharePoint UI to change the navigation.
So where do I start?
Sample:
Once again, instead of doing all the hard work here, I am going to point you to a sample developed by Stephen Huen. Download it and take a look at the good sample.
Like option 5, this allows for complete HTML output control and covers the dishwasher scenario too. However, the implementation is different to option 5.
The difference in this model is that the data source (navigation nodes) are "given" to you by the data source control. You don't need code to get the navigation items and you don't need to worry about showing or hidding navigation items based on navigation configured through the SharePoint UI. The data source will only give you the nodes which you are supposed to render based on the SharePoint navigation configured through the UI. Of course you could still add your custom logic beyond the standard SharePoint logic, which would be one of the reasons for developing this control in the first place.
At a high-level you would do the following to develop this control:
Instead of walking through every line of code which would make up such a control, I have put together a sample control, which has loads of comments included to help you understand the logic. However, let me give you a broad overview anyway.
Overview of the Sample
The requirement is to have complete control of the rendered HTML for the navigation e.g. nodes represented as a LI tags inside a UL tag, and CSS styles would be used to show navigation level 1, 2, 3 etc. The sample takes the navigation nodes from the data source control and creates an XML document which represents the navigation (this is done in the PerformDataBinding method). Each navigation node in the XML document is represented as a <node> element with attributes e.g. title, url and the navigation hierachy is represented by the node element hierachy i.e. a <node> element can have sibling and child <node> elements. All that is left to do is render your HTML in the Render method, and it is here where you can do what you like.
If a node is current, then we set the attribute "selected" in the XML document to true.
Three important points to be aware of:
If you add the sample control “as is” to a SharePoint site, you get the following:
Download the sample control here:
The sample is based on the HierarchicalDataBoundControl Class Sample found on MSDN, which does things slightly differently, and perhaps in your scenario could be better.
Some ideas for your control:
Disclaimer: This is sample code only, and therefore treat it as such. I have not tested all scenarios!! It works with the ASP Data Source provider control and the SharePoint data source provider, but I did not test it with XML data source provider i.e. I assume you are using it for SharePoint.