I am working on this variation of a main menu navigation where the submenu will display below the main navigational element once it is clicked. Basically I was struggling with how I was going to databind the submenu to the main menu item it was related too.
I went about solving this problem by using nested repeater controls.
1: <asp:repeater id="repMenu" runat="server">
2: <itemtemplate>
3: <%# DataBinder.Eval(Container.DataItem, "Name") %><br>
4: <asp:repeater id="repSubMenu" runat="server">
5: <itemtemplate>
6: <%# DataBinder.Eval(Container.DataItem, "MenuTitle") %>
7: </itemtemplate>
8: </asp:repeater>
9: </itemtemplate>
10: </asp:repeater>
The above HTML defines two Repeater Controls. The first one will display my DataBound Column Name from a Table in SQL Server. The second Repeater will display a column called Menu Title from a second DataBound Column.
Looking at the C# Code:
1: /// <summary>
2: /// Repeater Control
3: /// </summary>
4: protected System.Web.UI.WebControls.Repeater repMenu, repSubMenu;
5:
6: private void Page_Load(object sender, System.EventArgs e)
7: {
8: Section section = new Section();
9: repMenu.DataSource = section.SelectAll();
10: repMenu.DataBind();
11: }
12:
13: #region Web Form Designer generated code
14: override protected void OnInit(EventArgs e)
15: {
16: //
17: // CODEGEN: This call is required by the ASP.NET Web Form Designer.
18: //
19: InitializeComponent();
20: base.OnInit(e);
21: }
22:
23: /// <summary>
24: /// Required method for Designer support - do not modify
25: /// the contents of this method with the code editor.
26: /// </summary>
27: private void InitializeComponent()
28: {
29: this.Load += new System.EventHandler(this.Page_Load);
30: this.repMenu.ItemDataBound +=new RepeaterItemEventHandler(repMenu_ItemDataBound);
31: }
32: #endregion
33:
34: private void repMenu_ItemDataBound(object sender, RepeaterItemEventArgs e)
35: {
36: RepeaterItem item = e.Item;
37: repSubMenu = (Repeater) item.FindControl("repSubMenu");
38: DataRowView drv = (DataRowView) item.DataItem;
39: Page page = new Page();
40: page.SectionID = (int)drv.Row.ItemArray[0];
41: repSubMenu.DataSource = page.SelectAllWSectionIDLogic();;
42: repSubMenu.DataBind();
43:
44: }
I use LLBLGen to generate DataLayer Code automatically, your code may use DataTables, DataSets, XML, etc. The key to the code, however, is the ItemDataBound function (
Lines 34-44). Within this function is where the magic happens. The first line (
line 36) sets the line item that we are on in the first Repeater so that we can work with the data. In the second line (
line 37) we need to find the Second Repeater so we know how to work with it. Line 38 we need to move the DataItem Row into a DataRowView so that we can access the columns. I then initialize my datalayer class from LLBLGen and assign the sectionID from the DataRowView from the first Repeater into it. SectionID is specific to my database and tables. I use the methods/Properties Row.ItemArray from the DataRowView class. What ItemArray does is return the columns and the data that is bound in the first Repeater as an array. I found from debugging and looking at the variables while stepping through the code that the column I needed SectionID was at the 0 index of the array.
I then call the method again within the LLBLGen class and methods to bring back a DataTable of all the pages that relate to the section that I am in. I DataBind the repeater and I set the databound column I want to display MenuTitle in the HTML within the second Repeaters ItemTemplate.
The output of the nested table above would look something like this:
SectionPage
page
Page
SectionPage
Page
Page
I need to do more work to get the navigation menu to be useful like making the Section Name a linkbutton that hides/shows the nested Repeater. I'll blog on that when I figure that part out.
Update: based on comments from Travis I was able to update my code to streamline it a little better. Instead of this line:
40: page.SectionID = (int)drv.Row.ItemArray[0];
I was able to replace it with:
40: page.SectionID = (int)drv["ID"];
Thus making it easier to get at the columns needed from the parent repeater. Thanks Travis.

Thursday, January 19 2006 at 12:19 AM |
Tags: Programming