|   As we mentioned, there are essentially three elements that you can use to create navigation: postings, channels, and administrative functions. To utilize each of these elements, you'll use the PAPI, accessing the specific objects and properties. Examine the Objects and Properties Necessary for NavigationWith the exception of administrative functions, all navigation is built with channels or postings. Both channels and postings share common properties for building navigation within your Web site. A list of these properties follows, with a brief explanation of each. Keep in mind that if you closely study the .NET class reference in the CMS documentation, you'll find other properties that may be useful, but the properties listed here are the ones you'll use most frequently. 
 Creating Basic NavigationNow that you've familiarized yourself with the general design considerations and components of building navigation, let's examine some basic code samples to show you how to use what you've learned. As a start, let's look at basic channel navigation. By basic channel navigation, we're simply referring to getting a collection of channels from the PAPI and creating HTML that a content consumer can click on to navigate through that collection. Looking at Listing 14-1, you can see the basic traversal of a channel within the current channel. Listing 14-1 Basic channel navigation private void createBasicChannelNav(Channel startChannel) {       // Get a collection of channels from the startChannel       ChannelCollection navChannels = startChannel.Channels;       // Make sure we've gotten a collection back       if (navChannels != null)       {             // Create a new anchor link and iterate through each             // channel in the collection             HtmlAnchor navLink;             foreach(Channel navChannel in navChannels)             {                   // For each channel in the collection, create new anchor                   // link and add it to the .NET placeholder control on                   // on our page                   navLink = new HtmlAnchor();                   navLink.InnerText = navChannel.DisplayName;                   navLink.HRef = navChannel.Url;                   BasicChannelNav.Controls.Add(navLink);                   BasicChannelNav.Controls.Add(new LiteralControl("<BR>"));             }       } }  In this example, you'll notice that we're using the Channel object and the properties listed in Listing 14-1. We first retrieve a collection of channels in the start channel. Then, we iterate through the collection, pulling out the Url and DisplayName properties. We've created an ASPX page with a .NET placeholder control (note: this is not the CMS placeholder control) to hold the HtmlAnchor controls we're creating in our code (we could have also added the control to the page controls collection). In Figure 14-9 you can see the result of this code (the results of all code samples in this section are shown in this figure). Figure 14-9. Basic channel navigation in an ASPX page
 The next example is basic posting navigation. In Listing 14-2, you'll notice the code is very similar to the channel example. We simply get a collection of postings from the pass-in startChannel object and then iterate through the collection Listing 14-2 Basic posting navigation private void createBasicPostingNav(Channel startChannel) {       PostingCollection navPostings = startChannel.Postings;       if (navPostings != null)       {             HtmlAnchor navLink;             foreach(Posting navPosting in navPostings)             {                    navLink = new HtmlAnchor();                    navLink.InnerText = navPosting.DisplayName;                    navLink.HRef = navPosting.Url;                    BasicPostingNav.Controls.Add(navLink);                    BasicPostingNav.Controls.Add(new LiteralControl("<BR>"));             }       } }  Combining both of the prior examples and using recursion to iterate through a whole hierarchy, Listing 14-3 demonstrates mixed channel and posting navigation. Again, this sample builds on the prior two examples, with the exception of the recursive call. Listing 14-3 Basic channel and posting navigation[View full width]  private void createBasicChannelPostingNav(Channel startChannel, string navIndent) {       // Retrieve a collection of postings and channels       PostingCollection navPostings = startChannel.Postings;       ChannelCollection navChannels = startChannel.Channels;       // Create an anchor link       HtmlAnchor navLink = new HtmlAnchor();       // Write out the link to the start channel and add it       // to the .NET (not CMS) placeholder control       navLink.HRef = startChannel.Url;       navLink.InnerText = startChannel.DisplayName;       // Add an indent before the channel link; this will be additive for       // each recursive call       BasicChannelPostingNav.Controls.Add(new LiteralControl(navIndent));       // Add the link to the .NET placeholder control       BasicChannelPostingNav.Controls.Add(navLink);       BasicChannelPostingNav.Controls.Add(new LiteralControl("<br>"));       // Check to see if we got back a collection of postings       if (navPostings != null)       {             foreach(Posting navPosting in navPostings)             {                   // Write out a link to each posting                   navLink = new HtmlAnchor();                   navLink.InnerText = navPosting.DisplayName;                   navLink.HRef = navPosting.Url;                   // Add an indent to each posting (this will be additive as                   // we call the function recursively)                   BasicChannelPostingNav.Controls.Add(new LiteralControl  Our last sample is a very simple breadcrumb example. In Listing 14-4, notice that we use the parent property of the Channel object to "walk" up the hierarchy. Each time, we retrieve the appropriate properties from the channel we're working with and then reset the currentLocation variable to the parent of that channel. This function provides a good opportunity to create an overload for this function that accepts a posting instead of a channel; the basics of this function would remain the same, since the parent property of a posting also returns a channelitem. Although this function was implemented using a conditional loop, it could just easily have been implemented using recursion. Listing 14-4 Basic breadcrumb navigation private void createBasicBreadcrumbNav(Channel startChannel) {       // Create a variable to hold the start channel object       Channel myCurrentLocation = startChannel;       // Make sure you're not already at the "root" of your site       if (myCurrentLocation.Guid != myBaseChannel.Guid)       {             HtmlAnchor navLink;             // While you're not at your root create a breadcrumb             while(myCurrentLocation.Guid != myBaseChannel.Guid)             {                   // Create a new anchor link and set the appropriate                   // values                   navLink = new HtmlAnchor();                   navLink.HRef = myCurrentLocation.Url;                   navLink.InnerText = myCurrentLocation.DisplayName;                   // Add your breadcrumb to the .NET placeholder control                   BasicBreadcrumbNav.Controls.AddAt(0,navLink);                   BasicBreadcrumbNav.Controls.AddAt(0,new LiteralControl(" > "));                   // Set the current location to the parent of the                   // current location; we're walking one level up                   myCurrentLocation = myCurrentLocation.Parent;             }             // When the loop exits, create a new anchor object             // and set the appropriate value to the root of your             // breadcrumb             navLink = new HtmlAnchor();             navLink.HRef = myBaseChannel.Url;             navLink.InnerText = myBaseChannel.DisplayName;             BasicBreadcrumbNav.Controls.AddAt(0,navLink);       } }  BOTS Consulting Navigation SamplesReviewing basic examples is nice, but it's always better to see the navigation implemented in "real" sites. BOTS is certainly not a very complicated site, but we thought it was useful to share the main and left navigation code as a way of comparing the basic examples to code that had a few exceptions. Both the left and main navigation code was implemented in a user control that was dropped onto a page for ease of reuse. In Listing 14-5, you'll notice that we're not taking in a value to start the navigation. In the function, BOTS is grabbing a very specific channel and starting with that. They made the assumption that this code would be used only in their site. This isn't a bad technique, but it does tend to limit reuse. As you can see, there aren't any exceptions in this code; it's really just basic channel navigation with some HTML formatting. Listing 14-5 BOTS Consulting main navigation[View full width]  private void createMainNavigation() {       try       {             // Retrieve the main BOTS Consulting channel             Channel NavParentChannel = (Channel)CmsHttpContext. Current.Searches.GetByPath  In the following listings, we provide various "interesting" sections of the left navigation. The code is somewhat lengthy, so we're listing only certain portions that need to be highlighted. In Listing 14-6, we've provided the task-based navigation. These few lines of code provide a way to create a new posting based on the Press Release Detail template of the In the Press channel. Notice that there are some conditions wrapped around the link so that a content contributor can't accidentally create a posting with the wrong template or in the wrong channel. Listing 14-6 Task-based publishing in the Web Author[View full width]  // Check to see if the posting is in EDIT mode if ((WebAuthorContext.Current.Mode == WebAuthorContextMode.PresentationUnpublished) &&       (CmsHttpContext.Current.Channel.Name.ToString() == "press") &&       CmsHttpContext.Current.Posting.Template.Name == "Press Release Detail") {       // Get the template and channel object for this posting       Template thisTemplate = CmsHttpContext.Current.Posting.Template;       Channel thisChannel = CmsHttpContext.Current.Channel;       // Create the task link       HtmlAnchor taskPublishingLink = new HtmlAnchor();       // Get a URL to a new posting based on the Press Release Detail template       taskPublishingLink.HRef = WebAuthorContext.Current.GetAuthoringNewUrl(thisTemplate  In Listing 14-7, we're showing how BOTS handles most of the left navigation, including the channels and postings. Notice the special conditions with regard to the default posting and the custom property setting that determines whether to show postings in the left navigation or not. Again, in some cases they want postings to display and in other they don't. In an effort to make the code more flexible, they're examining a custom property on the channel to determine whether postings should be listed. Listing 14-7 The left navigation logic for BOTS[View full width]              private void BuildLeftNavTable(Channel StartChannel)             {                   // Define the necessary variables for creating the nav table                   // and the links                   HtmlAnchor NavigationLink;                   TableRow NewTableRow;                   TableCell NewTableCell;                   Literal TextPlaceholder;                   // Get a collection of channels in the pass-in channel                   ChannelCollection SubChannels = StartChannel.Channels;                   // Check to make sure we got back a collection                   if(SubChannels != null)                   {                         // Iterate through the collection                         foreach(Channel SubChannel in SubChannels)                         {                               // Create a new row, cell and anchor link                               NewTableRow = new TableRow();                               NewTableCell = new TableCell();                               NavigationLink = new HtmlAnchor();                               NavigationLink.HRef = SubChannel.Url;                               // If the channel we're on matches the current channel                               // add bolding to the style                               if (SubChannel.Guid.ToString() == CmsHttpContext.Current  It is a little more complex than the main navigation, but still uses the concepts we demonstrated in the basic navigation samples. In addition, it accounts for the unique situations within the BOTS site.  |