Click here to Skip to main content
15,891,184 members
Articles / Web Development / ASP.NET
Article

One approach to data binding with nested Repeaters

Rate me:
Please Sign up or sign in to vote.
3.29/5 (6 votes)
18 Apr 2008CPOL2 min read 35.8K   172   16   2
Binding a variable number of DataTable objects using nested Repeaters.

Introduction

This article is a small demo project that uses nested Repeaters to display a variable number of DataTable objects with the same schema.

Using the code

Before I continue, I realize that the following solution is not exactly the most elegant, but it works, and criticisms are most welcome.

We have two Repeater controls. The inner Repeater control is placed within a User Control, while the outer Repeater is contained with the APSX page, with its <ItemTemplate> being the User Control.

Before we go into the details of the controls, first, let’s introduce the small customDataItem.cs class in the App_Code folder. For some reason, when I bind a DataSet, the Repeaters do not render all of the tables as expected, but actually repeats the last DataTable in the set several times. So, the alternative approach was to encapsulate each of the DataTable object within a new object. So, I created a class called CustomDataItem.

C#
public class CustomDataItem 
{ 
    private DataTable _Data;
    public DataTable Data { get { return _Data; } set { _Data = value; } } 

    public CustomDataItem(DataTable data) 
    { 
        _Data = data; 
    } 
}

As you can see, it’s a very simple class that encapsulates a DataTable object passed as a parameter to the constructor. That’s it, basically.

Next, we have the User Control (.ascx) code that contains the inner Repeater. It’s fairly simple and self-explanatory. You will notice that I have a Literal control as a header. The Literal text will be set to the table name when data bound.

HTML
<h2><span><asp:Literal runat="server" ID="ltrTableName"/></span></h2> 
<asp:Repeater ID="innerRep" runat="server"> 
<HeaderTemplate> 
<table cellpadding="2" cellspacing="5" border="true"> 
<thead> 
<tr> 
<th><b>Name</b></th> 
<th><b>Address</b></th> 
<th><b>PostCode</b></th> 
</tr> 
</thead> 
</HeaderTemplate> 
<ItemTemplate> 
<tr> 
<td><%# DataBinder.Eval(Container.DataItem,"Name") %></td> 
<td><%# DataBinder.Eval(Container.DataItem,"Address") %></td> 
<td><%# DataBinder.Eval(Container.DataItem,"PostCode") %></td> 
</tr> 
</ItemTemplate> 
<FooterTemplate> 
</table> 
</FooterTemplate> 
</asp:Repeater>

Now, for the code-behind of the user control:

C#
public partial class InnerRepeaterUserControl : System.Web.UI.UserControl 
{
  private CustomDataItem _DataItem; 
  public CustomDataItem DataItem { get { return _DataItem; } 
                                 set { _DataItem = value; } }
  protected void Page_Load(object sender, EventArgs e) 
  { 
    if (!IsPostBack) 
         BindData(); 
  }
  protected override void OnPreRender(EventArgs e) 
  { 
    base.OnPreRender(e); 
  } 
  private void BindData() 
  { 
    try 
    { 
         binnerRep.DataSource = _DataItem.Data;
         innerRep.DataBind(); 
         ltrTableName.Text = _DataItem.Data.TableName; 
    } 
    catch { }
  }

The BindData() method binds the DataTable contained within the CustomDataItem object and the Literal text to the table name. The CustomDataItem is passed in the innerRepeater_DataBound() event fired on the main ASPX page. We will go into details a little later on.

The ASPX code on the web page is simple enough. Here, all we do is register the user control and add the outer Repeater, as well as set the reference to the outer Repeater's ItemDataBound method.

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
         CodeFile="Default.aspx.cs" Inherits="_Default" %> 
<%@ Register Src="~/InnerRepeaterUserControl.ascx" 
         TagPrefix="uc" TagName="InnerRep" %> 
<!DOCTYPE html PUBLIC 
"-//W3C//DTD XHTML 1.0 Transitional//EN"  
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head runat="server"> 
<title>Repeater Demo</title> 
</head> 
<body> 
<form id="form1" runat="server"> 
<div> 
<asp:Repeater runat="server" ID="outerRepeater" 
       onItemDataBound="outerRepeater_ItemDataBound"> 
<ItemTemplate> 
<uc:InnerRep runat="server" ID="tblInnerRep" />
</ItemTemplate> 
</asp:Repeater> 
</div> 
</form> 
</body> 
</html>

The C# code-behind of the web page is where most of the work is done. In this example, I created three simple data tables in the code in createDataTables(), and added them to a generic list of CustomDataItem objects.

BindData() simply calls the method and binds the list to the outer Repeater.

Finally, in outerRepeater_ItemDataBound, we find the inner Repeater control, cast the e.DataItem of the outer Repeater to a CustomDataItem, and set this as the inner Repeater's DataItem.

C#
protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!Page.IsPostBack) 
    { 
         base.OnInit(e); 
         BindData(); 
     } 
} 
private void BindData() 
{ 
    List<CustomDataItem> dataItems = createDataTables(); 
    outerRepeater.DataSource = dataItems; 
    outerRepeater.DataBind(); 
} 
private List<CustomDataItem> createDataTables() 
{ 
    //instantiate Generic list & set capacity to 3 
    List<CustomDataItem> dataItems = new List<CustomDataItem>(3); 
    // Logic for creating example DataTable objects here 
    //....... 
    //....... 
    //create new CustomDataItems and add to List<> 
    dataItems.Add(new CustomDataItem(tbl1)); 
    dataItems.Add(new CustomDataItem(tbl2)); 
    dataItems.Add(new CustomDataItem(tbl3)); 
    return dataItems; 
} 

protected void outerRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) 
{ 
    if (e.Item.DataItem is CustomDataItem) 
    { 
           CustomDataItem dataItem = e.Item.DataItem as CustomDataItem; 
           InnerRepeaterUserControl ctrl = 
                 e.Item.FindControl("tblInnerRep") as InnerRepeaterUserControl; 
           if (ctrl != null) 
               ctrl.DataItem = dataItem; 
     } 
}

Points of interest

None.

History

No changes.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Junior) Online bookmakers
Panama Panama
Employed as a Junior .NET dev for an online bookmakers based in Malta.

Comments and Discussions

 
GeneralThis implementation lacks alot... Pin
Yang Yu18-Apr-08 4:34
Yang Yu18-Apr-08 4:34 
I just have a few things to say to help you out.

1. Comments on the business logic implementation - Why not use object orientation for data binding.
You can create a recursive class. Datatables are not very helpful since they are huge in metadata size, and they are ment to be used with DataViews and doing custom filters etc. They are not ment to be used as data structures simply to store data.
2. Comments on the GUI implementation - Why not create a custom class that implements ITemplate, aswell stores the Object Classes it represents. So you would have one usercontrol, the template used will be this class which renders the same usercontrol.
GeneralRe: This implementation lacks alot... Pin
sean_mufc20-Apr-08 21:48
sean_mufc20-Apr-08 21:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.