How do I make a dynamic category and product menu in OrderCentral?


Many OrderCentral site designers want a dynamic product menu with categories and products displayed.  This functionality can be accomplished by using two datasets that are available in the OrderCentral.elements.categoryUI class.
All Categories dataset: dsTopCategories (populated by sql procedure: xct_spGetSubCategories)
All Category To Items dataset: dsTopCategoryItems(populated by sql procedure: xct_spGetCategoryItems)

To make a product menu create an .ascx control file and have it inherit from OrderCentral.elements.categoryUI.
Example header tag for your new control:
<%@ Control Language="c#" AutoEventWireup="false" Inherits="OrderCentral.elements.categoryUI" %>

In this new file you can use inline scripting to access the two datasets listed above or extend the class and tie to your own controls.  The top 5 category levels are contained in the dsTopCategories dataset.  Each level is in a seperate DataTable.
dsTopCategories.Tables[X] = All xctCategory.categoryLevel = X active categories

Example on how to loop and print out all TOP level categories:
<% for(System.Int32 i=0; i<dsTopCategories.Tables[0].Rows.Count; i++) {%>
 <li><a href="category.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&categoryLevel=0"><%=Server.HtmlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%></a></li>
<% } %>

Example on how to loop and print out all TOP level categories AND their immediate subcategories.
<ul>
<% for(System.Int32 i=0; i<dsTopCategories.Tables[0].Rows.Count; i++) {%>
 <li>
 <a href="category.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&categoryLevel=0"><%=Server.HtmlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%></a>
 <% System.Data.DataRow[] drSubs1 = dsTopCategories.Tables[1].Select("parentCategoryID='" + dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim().Replace("'", "''") + "'", "sortIndex, categoryName");
 <% if (drSubs1.Length > 0){%>
  <ul>
  <% for (System.Int32 j=0; j<drSubs1.Length; j++){ %>
  <li><a href="category.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&category2=<%=Server.UrlEncode(drSubs1[j]["categoryID"].ToString().Trim())%>&category2Name=<%=Server.UrlEncode(drSubs1[j]["categoryName"].ToString().Trim())%>&categoryLevel=1"><%=Server.HtmlEncode(drSubs1[j]["categoryName"].ToString().Trim())%></a></li>
  <% } %>
  </ul>
 <% } %>
 </li>
<% } %>
</ul>

Example on how to loop and print out all TOP level categories AND the items associated to them.
<ul>
<% for(System.Int32 i=0; i<dsTopCategories.Tables[0].Rows.Count; i++) {%>
 <li>
 <a href="category.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&categoryLevel=0"><%=Server.HtmlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%></a>
  <% System.Data.DataRow[] drItems = dsTopCategoryItems.Tables[0].Select("categoryID='" + dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim().Replace("'", "''") + "' AND categoryLevel=0", "sortIndex, name"); %>
  <% if (drItems.Length > 0){%>
        <ul>
  <% for (System.Int32 j=0; j<drItems.Length; j++){%>
   <% if (drItems[j]["Type"].ToString().Trim() == "P"){%>
   <li><a href="productDetail.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&itemID=<%=Server.UrlEncode(drItems[j]["itemID"].ToString().Trim())%>"><%=Server.HtmlEncode(drItems[j]["name"].ToString().Trim())%></a></li>
   <% } else if (drItems[j]["Type"].ToString().Trim() == "PG"){%>
   <li><a href="productGroup.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&itemID=<%=Server.UrlEncode(drItems[j]["itemID"].ToString().Trim())%>"><%=Server.HtmlEncode(drItems[j]["name"].ToString().Trim())%></a></li>
   <% } else if (drItems[j]["Type"].ToString().Trim() == "G"){%>
   <li><a href="category.aspx?category1=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryID"].ToString().Trim())%>&category1Name=<%=Server.UrlEncode(dsTopCategories.Tables[0].Rows[i]["categoryName"].ToString().Trim())%>&category2=<%=Server.UrlEncode(drItems[j]["itemID"].ToString().Trim())%>&category2Name=<%=Server.UrlEncode(drItems[j]["name"].ToString().Trim())%>&categoryLevel=1"><%=Server.HtmlEncode(drItems[j]["name"].ToString().Trim())%></a></li>
   <% } %>
  <%}%>
  </ul>
 </li>
<% } %>
</ul>

For sites where category and product access is not restricted by customer (all customers have access to the same categories and products) there are two optional properties to cache the data on the webserver.  This reduces the number of hits to the database and can speed up page load time dramatically.
System.Boolean cacheDSTopCategories  (Optional, default: false)
System.Boolean cacheDSTopCategoryItems (Optional, default: false)

Example tag for a product menu with caching enabled:
<xct:productMenuUI id="productMenuUI" runat="server" cacheDSTopCategories="TRUE" cacheDSTopCategoryItems="TRUE" />