In this article we will see that how we can use the nested repeaters to display information in a categorized way. We will use the Northwind database and will learn to display the information in the Categories and in the Products table in a categorized way.
Introduction:
In this article we will see that how we can use the nested repeaters to display information in a categorized way. We will use the Northwind database and will learn to display the information in the Categories and in the Products table in a categorized way.
What is categorized way?
Most of you might be thinking what does categorized data means. To have a better picture take a look at the screen shot of the ArticleCategory.aspx page of the GridViewGuy. To view this page simply browse to the GridViewGuy website and click on the Articles link contained in the menu on the left.
As, you can see from the screenshot above that all the articles are well placed in their respective categories. This is what I refer to as displaying the data in a categorized way.
The Database:
In this article we will be using the Northwind database. The stored procedure is given below which gets the Categories and the Products from the Northwind database tables.
CREATE PROCEDURE [usp_GetProductsForCategories] AS SELECT * FROM Categories WHERE CategoryID IN ( SELECT CategoryID FROM Products ) SELECT p.ProductID, p.ProductName,p.CategoryID FROM Products p |
The stored procedure returns two sets. The first set contains all the columns of the Categories table which have the corresponding record in the Products table. The second set contains the ProductID, ProductName and the CategoryID from the Products table. We will use the DataSet Relation to join the two sets together.
Setting up the Repeater Controls:
Now, let's take a look at the Repeater controls which are used to display the data on the screen. We will be using nested repeaters for our scenario. The outer repeater will display the category name and the inner repeater will display the articles related to that category. Take a look at the code below which creates the outer repeater control.
<asp:Repeater
ID="outerRep"
runat="server"
OnItemDataBound="outerRep_ItemDataBound"> <ItemTemplate> <div> <asp:Label Font-Size="Large" Font-Bold="true" ID="lblCategoryName" runat="server" Text='<%# Eval("CategoryName") %>' /> </div> </asp:Repeater> |
The outer repeater which is defined as "outerRep" contains a simple Label control which is used to display the category name from the database. Now, let's see the inner repeater which will be used to display the products of the corresponding category.
<asp:Repeater
ID="outerRep"
runat="server"
OnItemDataBound="outerRep_ItemDataBound"> <ItemTemplate> <div> <asp:Label Font-Size="Large" Font-Bold="true" ID="lblCategoryName" runat="server" Text='<%# Eval("CategoryName") %>' /> </div> <asp:Repeater ID="innerRep" runat="server"> <ItemTemplate> <div style="background-color:AliceBlue"> <asp:HyperLink ID="hlProductName" runat="server" Text='<%# Eval("ProductName") %>' /> </div> </ItemTemplate> </asp:Repeater> |
The inner repeater which is defined as "innerRep" contains a simply ASP.NET HyperLink control which displays the product name as a link.
The example above does not display the HyperLink control as a clickable link since, I have not bound any field to the NavigateUrl property of the HyperLink control. If you have a link field in your database table you can easily bind that link field to the NavigateUrl property and it will be rendered as a link.
Populating the Repeaters:
The last and the most important step is to populate the Repeater controls. Take a look at the BindData method which populates the DataSet and create relationship on the DataSet.
private
void BindData()
{ SqlConnection myConnection = new SqlConnection(ConnectionString); SqlCommand myCommand = new SqlCommand("usp_GetProductsForCategories", myConnection); myCommand.CommandType = CommandType.StoredProcedure; SqlDataAdapter ad = new SqlDataAdapter(myCommand); DataSet ds = new DataSet(); ad.Fill(ds); // Attach the relationship to the dataSet ds.Relations.Add(new DataRelation("CategoriesRelation",ds.Tables[0].Columns["CategoryID"], ds.Tables[1].Columns["CategoryID"])); outerRep.DataSource = ds.Tables[0]; outerRep.DataBind(); } |
We have used the SqlDataAdapter to fill the DataSet container. Once, the DataSet is filled the relationship is created between the Table[0] (Categories) and the Table[1] (Products). Finally, the Categories table is assigned to the outer repeater control.
What about the Populating the Inner Repeater?
The technique that I have used to populate the inner repeater is to utilize the Item_DataBound event of the outer repeater. Check out the Item_DataBound event of the outer repeater control.
protected void
outerRep_ItemDataBound(object
sender, RepeaterItemEventArgs
e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { DataRowView drv = e.Item.DataItem as DataRowView; Repeater innerRep = e.Item.FindControl("innerRep") as Repeater; innerRep.DataSource = drv.CreateChildView("CategoriesRelation"); innerRep.DataBind(); } |
First, we check that if the row belong to the ItemTemplate or the AlternatingItemTemplate. Then we get a DataRowView object of the current data item. We find the inner repeater control using the FindControl method of the current item. And finally assign the DataView which is returned from the CreateChildView method of the DataRowView object. Take a look at the screenshot below to have a clear idea of what the output looks like.
As, you can see from the image above all the products are displayed in the correct categories.
Conclusion:
The article explained that how easily you can use the DataSet Relations to create relations between two tables. Although a DataSet is quite simple to use but it is a heavy container and should be used wisely. I highly recommend using entity classes and collections for the same purpose.
I hope you liked the article, happy coding!