Almost every navigation example in this book used literals, tables, and a few HTML Anchors to create navigation. Although this is a perfectly acceptable, and sometimes preferable, method of creating navigation in your site, it's also possible to use other server controls, like a Tree control or a Datalist. To make it easier on us to describe, we'll call this methodology "creating navigation with alternative controls." In Listings 36-5 and 36-6, we show you two ways of creating navigation using alternative controls. Keep in mind that, in the case of the Tree control specifically, there are performance considerations that aren't apparent in our samples and Microsoft doesn't support this control any longer (it's included in the IE Web Controls). Listing 36-5 Creating a site map with a Tree control[View full width] protected Microsoft.Web.UI.WebControls.TreeView myTreeView; private void Page_Load(object sender, System.EventArgs e) { // Set the "root" of our site map to the home channel of // BOTS consulting Channel myStartChannel = (Channel)CmsHttpContext.Current.Searches.GetByPath(" /Channels/botsconsulting"); // Turn off the lines and the plus/minus signs, making // the tree control look less like a "tree" myTreeView.ShowLines = false; myTreeView.ShowPlus = false; // Call the BUILDSITEMAP function, passing in the starting // channel and a null reference for the parentChannel (since // we're starting with the root) BuildSiteMap(myStartChannel,null); } /// <summary> /// This function recursively builds a site map using a TreeControl. /// The function only displays the channels and not the postings to /// improve performance. The function will generally work well on /// smaller sites, but may be sluggish on larger, more complicated /// sites. /// </summary> /// <param name="(Channel) startChannel"></param> /// <param name="(TreeNode) parentTreeNode"></param> public void BuildSiteMap(Channel startChannel, TreeNode parentTreeNode) { // Create a new tree node TreeNode myNewNode = new TreeNode(); // Add the styles we want to our node (yes, we could have used // CSS, but we were lazy) myNewNode.DefaultStyle.Add("FONT-FAMILY","verdana"); myNewNode.DefaultStyle.Add("FONT-WEIGHT","bold"); myNewNode.DefaultStyle.Add("COLOR","gray"); // Set the NavigateUrl property to the URL of the current channel // Set the Text property to the displayname myNewNode.NavigateUrl = startChannel.Url; myNewNode.Text = startChannel.DisplayName; // Check to see if the parentTreeNode is null. If it is // this is the first time this function has been called, so // we know we're at the root. if(parentTreeNode == null) { // Add the new node to the myTreeNode control on our user // control. myTreeView.Nodes.Add(myNewNode); } else { // If we were given a parent, add our new node to that // parent node and make sure it's expanded. parentTreeNode.Nodes.Add(myNewNode); parentTreeNode.Expanded = true; } // If the current channel has subchannels, recursively // call this function to finish out the rest of the tree. if (startChannel.Channels.Count > 0) { foreach(Channel subChannel in startChannel.Channels) { BuildSiteMap(subChannel,myNewNode); } } } The code in Listing 36-5 resides inside a user control. The user control had a Tree control added at design time, and we create the nodes within the tree at runtime. During the Page_Load event, we simply set up the Tree control and get a reference to the root channel. We then recursively traverse the tree to gather all the nodes. As we mentioned in the code comments, this particular implementation will work for relatively small sites. However, we've seen similar implementations on larger sites perform poorly, through a combination of sheer processing time and the size of the resulting property bag. If you implement this control on your site, be sure to properly load test the site to ensure optimal performance. Next, in Listing 36-6, you'll see a sample of our left navigation using a Datalist. In this sample, we're creating a data source dynamically from the collection of postings and then binding that data source to our Data list. A display template handles all of the formatting. Thanks to Drew Jones for this contribution. Listing 36-6 Creating navigation with a Datalistprotected System.Web.UI.WebControls.DataList myDataList; private string startchannelpath; public string startChannelPath { get { return startchannelpath; } set { startchannelpath = value; } } private void Page_Load(object sender, System.EventArgs e) { // Check to see if a path has been provided by the developer // If one hasn't been provided, get the path to the current channel. if(startChannelPath =="") {startchannelpath = CmsHttpContext.Current.Channel.Path;} // Set a reference to the channel indicated by the startChannelPath // property Channel startChannel = (Channel)CmsHttpContext.Current.Searches. GetByPath(startchannelpath); // If an invalid path was provided, set the startChannel to the current // channel if (startChannel == null) {startChannel = CmsHttpContext.Current.Channel;} // Call the navigation function BuildNavigation(startChannel); } public void BuildNavigation(Channel startChannel) { // Check to see if startChannel is null if (startChannel != null) { // Set the datasource of my list to the collection of channels myDataList.DataSource = startChannel.Channels; // Bind the DataList to the datasource myDataList.DataBind(); } } The code in Listing 36-6 sets up the Datalist and binds the collection of postings. However, you also have to provide a "template" that defines how to display the data when it's rendered. In our case, we just want a simple list. In Listing 36-7 we've provided the item template that controls the display of the Datalist. In Figure 36-4, you can see the result of this new user control when it is added to the general template in the BOTS site. We've simply added it just below the existing navigation. It fundamentally looks the same as the original navigation; it just ultimately required fewer lines of code to create. It may not be appropriate for all situations, but we thought it was cool. Listing 36-7 Item template for the Datalist[View full width] <table border=0> <tr> <td> </td> <td> <hr size=1> <asp:DataList runat="server" Font-Name="Verdana"> <ItemTemplate> <a style="COLOR: gray" href="<%# DataBinder.Eval(Container .DataItem,"Url")%>"> <%# DataBinder.Eval(Container.DataItem, "DisplayName") %> </a> </ItemTemplate> </asp:DataList> <hr size=1> </td> </tr> </table> Figure 36-4. Both original and Datalist left navigation on the BOTS site |