I created a project that displays data by month using nested repeaters, it is uploaded to Google Docs (just click File> Save to download .zip).
Here is a brief overview of how this works:
Assuming you have a simple db order table with the following columns
- OrderId
- Product
- number
- DateOfSale
Process
- Follow the stored procedure to get the months for a given year (I used the EntityFramework functions, you can change this to ADO.NET, LINQ, etc.)
- Bind the returned months to the label of the main repeater (these will be your headers).
- To
OnItemDataBound event of the main repeater, this event is fired every time an element is attached to the repeater . - Inside
OnItemDataBound execute the stored procedure to get all records for a specific month and year and just bind the returned data to the child relay - Add some jQuery to show and hide divs and you are set up.
code
Stored Procedures:
CREATE PROCEDURE dbo.GetMonthsByYear @Year INT AS BEGIN SELECT DISTINCT DATENAME(Month,DateOfSale) AS [Month] FROM Orders WHERE Year(DateOfSale) = @Year END CREATE PROCEDURE dbo.GetOrdersByMonth @Month NVARCHAR(15), @Year INT AS BEGIN SELECT * FROM Orders WHERE (Year(DateOfSale) = @Year) AND DATENAME(MONTH,DateOfSale) = @Month END
Aspx:
<head runat="server"> <script src="Scripts/jquery-1.7.1.js" type="text/javascript"></script> <script type="text/javascript"> var showHide; $(document).ready(function () { showHide = function (control) { var parent = $(control).next(); var display = parent.css('display'); if (display == "none") { parent.fadeIn('slow'); } else { parent.fadeOut('slow'); } }; }); </script> <style type="text/css"> .detail { height:300px; display:none; width: 100%; border: 1px solid black; } .header { vertical-align: top; padding: 3px; height: 30px; background: black; color: White; font-weight: bold; } </style> <title>Nested Repeater</title> </head> <body> <form id="form1" runat="server"> <div> Select year: <asp:TextBox ID="txtYear" runat="server" /><br /> <asp:Button ID="btnSearch" runat="server" Text="Search" OnClick="Search" /><br /> <asp:Repeater ID="masterRepeater" runat="server" OnItemDataBound="ItemDataBound"> <ItemTemplate> <div id='<%# Container.DataItem %>' class="header" onclick="showHide(this);"> <asp:Label ID="lblMonth" runat="server" Text='<%# Container.DataItem %>' /> </div> <div class="detail"> <asp:Repeater ID="detailRepeater" runat="server"> <HeaderTemplate> <span style="text-decoration: underline">Product</span><br /> </HeaderTemplate> <ItemTemplate> <asp:Label ID="lblName" runat="server" Text='<%# Bind("Product") %>' /> <asp:Label ID="lblQuantity" runat="server" Text='<%# Bind("Quantity") %>' /> <asp:Label ID="lblDateOfSale" runat="server" Text='<%# Bind("DateOfSale") %>' /><br /> </ItemTemplate> </asp:Repeater> </div> </ItemTemplate> </asp:Repeater> </div> </form> </body>
Code behind:
protected void Search(object sender, EventArgs e) { int year = 0; if (Int32.TryParse(txtYear.Text, out year)) { orderEntities orders = new orderEntities(); List<string> months = orders.GetMonthByYear(year).ToList(); masterRepeater.DataSource = months; masterRepeater.DataBind(); } } protected void ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { int year = 0; if (Int32.TryParse(txtYear.Text, out year)) { Label lblMonth = e.Item.FindControl("lblMonth") as Label; if (lblMonth != null) { string month = lblMonth.Text; Repeater detailRepeater = e.Item.FindControl("detailRepeater") as Repeater; if (detailRepeater != null) { orderEntities orders = new orderEntities(); var ordersByMonth = orders.GetOrdersByMonth(month, year).ToList(); detailRepeater.DataSource = ordersByMonth; detailRepeater.DataBind(); } } } } }
Result:

source share