Friday, July 30, 2010

How to combine two asp.net Menu Controls with single site map and populate second menu based on first menu selection

Demo:
 
To handle multiple asp.net menu controls based on single site map data source:
  1. Convert all the links of the first menu to perform a postback instead of rendering as links.
  2. Use link button instead of hyperlink
  3. In the code behind (usually in the master page) handle link button event and read the site map in to XPathDocuemnt, create navigator and perform a XPath query for the relevent node
  4. Populate the second menu with the selected XML node
  5. Use an recursive method to populate all the child menu items
  6. In this article I have not used a application variable, but it is better to hold the Web.sitemap file (XPathNavigator) instead of reading on each menu click.
  7. I have used empty namespace, but if you use a namespace (usually sitemap file comes with a namespace) you have to change to XPath logoc accordingly.
Site.Master page:
<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head id="Head1" runat="server">
    <script runat="server">
        protected void PopulateLeftNagivation(object sender, CommandEventArgs e)
        {
            this.mnuLeftNavigation.Items.Clear();
            XPathDocument doc = new XPathDocument(Server.MapPath("~/Web.sitemap"));
            XPathNavigator navigator = doc.CreateNavigator();
            XPathNodeIterator reader = navigator.Select(
                string.Format("/siteMap/siteMapNode[@url='']/siteMapNode[@url='{0}']/siteMapNode",
                Path.GetFileName(e.CommandArgument.ToString())));
            this.BuildLeftMenu(this.mnuLeftNavigation.Items, reader);
        }
        private void BuildLeftMenu(MenuItemCollection items, XPathNodeIterator reader)
        {
            while (reader.MoveNext())
            {
                MenuItem item = new MenuItem(reader.Current.GetAttribute("url"string.Empty),
                    reader.Current.GetAttribute("title"string.Empty));
                items.Add(item);
                if (reader.Current.HasChildren)
                    this.BuildLeftMenu(item.ChildItems,
                        reader.Current.SelectChildren("siteMapNode"string.Empty));
            }
        }        
    </script>
    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="Form1" runat="server">
    <asp:ScriptManager runat="server" ID="ScriptManager2"></asp:ScriptManager>
    <div class="page">
        <div class="main">
                <asp:UpdatePanel runat="server" ID="upnlNavigation">
                    <ContentTemplate>
                        <div class="NavigationWrapper">
                            <div class="TopNanvigation">
                                <asp:SiteMapDataSource runat="server" ID="SiteMapDataSource" ShowStartingNode="false" />
                                <asp:Menu runat="server" ID="mnuTopNavigation" Orientation="Horizontal" DataSourceID="SiteMapDataSource"
                                    StaticDisplayLevels="1" MaximumDynamicDisplayLevels="0">
                                    <StaticItemTemplate>
                                        <asp:LinkButton 
                                            runat="server" 
                                            ID="lnkItem" 
                                            CommandArgument='<%# Eval("NavigateUrl") %>' 
                                            OnCommand="PopulateLeftNagivation">
                                            <%# Eval("Text"%>
                                        </asp:LinkButton>
                                    </StaticItemTemplate>
                                </asp:Menu>
                            </div>
                            <div class="LeftNavigation">
                                <asp:Menu runat="server" ID="mnuLeftNavigation" />
                            </div>
                        </div>
                    </ContentTemplate>
                </asp:UpdatePanel>
            <div class="MainContent">
                <asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server"/>
            </div>
        </div>
        <div class="clear">
        </div>
    </div>
    <div class="footer">
        
    </div>
    </form>
</body>
</html>

Web.sitemap file (please not no name space)
<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
    <siteMapNode url="" title=""  description="">
      <siteMapNode url="Page1.aspx" title="Item 1"  description="">
        <siteMapNode url="SubPage11.aspx" title="Sub Item 11" />
        <siteMapNode url="SubPage12.aspx" title="Sub Item 12" >
          <siteMapNode url="SubPage121.aspx" title="Sub Item 121" />
          <siteMapNode url="SubPage122.aspx" title="Sub Item 122" />
          <siteMapNode url="SubPage123.aspx" title="Sub Item 123" />
        </siteMapNode>
        <siteMapNode url="SubPage13.aspx" title="Sub Item 13" />
        <siteMapNode url="SubPage14.aspx" title="Sub Item 14" />
        <siteMapNode url="SubPage15.aspx" title="Sub Item 15" />
      </siteMapNode>
      <siteMapNode url="Page2.aspx" title="Item 2"  description="">
        <siteMapNode url="SubPage21.aspx" title="Sub Item 21" />
        <siteMapNode url="SubPage22.aspx" title="Sub Item 22" />
        <siteMapNode url="SubPage23.aspx" title="Sub Item 23" />
      </siteMapNode>
      <siteMapNode url="Page3.aspx" title="Item 3"  description="">
        <siteMapNode url="SubPage31.aspx" title="Sub Item 31" />
        <siteMapNode url="SubPage32.aspx" title="Sub Item 32" />
        <siteMapNode url="SubPage33.aspx" title="Sub Item 33" />
        <siteMapNode url="SubPage34.aspx" title="Sub Item 34" />
      </siteMapNode>
      <siteMapNode url="Page4.aspx" title="Item 3"  description="">
        <siteMapNode url="SubPage41.aspx" title="Sub Item 41" />
        <siteMapNode url="SubPage42.aspx" title="Sub Item 42" />
      </siteMapNode>
      <siteMapNode url="Page5.aspx" title="Item 3"  description="">
        <siteMapNode url="SubPage51.aspx" title="Sub Item 51" />
        <siteMapNode url="SubPage52.aspx" title="Sub Item 52" />
        <siteMapNode url="SubPage53.aspx" title="Sub Item 53" />
        <siteMapNode url="SubPage54.aspx" title="Sub Item 54" />
      </siteMapNode>
    </siteMapNode>
</siteMap>

No comments:

iPhone Launch Screen Sizes

iPhone Portrait iOS 8 Retina HT 5.5 = 1242 X 2208 Retna HD 4.7 = 750 X 1134 iPhone Landscape iOS 8 Retina HD 5.5  2208 X 1242 iPho...