Monday, September 19, 2005

Repeater - ITemplate

Simple code to demonstrate how a custom control that has repeater as its child control defines its template.
Three classes, MyHeaderTemplate, MyItemTemplate and MyFooterTemplate derive from Itemplate class and hence implement the InstantiateIn method.

The Repeater’s DataBind() method calls the InstantiateIn methods of the HeaderTemplate, ItemTemplate(once for each row of data in the DataTable) and FoorterTemplate respectively.

The implementation of the ItemTemplate’s InstantiateIn method creates a TableRow and a TableCell for each Column of the DataTable and adds it to the repeater control’s RepeaterItem (passed in to the InstantiateIn method).
The BindRow method handles the DataBinding event of each of the rows. It is called for each row after the InstantiateIn method returns.
The implementation of this method adds some client side attributes to the current row and updates the format of the DateTime columns.


public class MyItemTemplate : ITemplate
{
//DataTable is supplied by the custom control and has a set of rows.
private DataTable dt = null;
private WebControl webControl;

public MyItemTemplate(DataTable dt, WebControl webControl)
{
this.dt = dt;
this.webControl = webControl;
}

public void InstantiateIn(Control container)
{
TableRow _row = new TableRow();

for(int i=0;i < dt.Columns.Count;++i)
{
TableCell _column = new TableCell();
_row.Cells.Add(_column);
}
_row.DataBinding+=new EventHandler(BindRow);
container.Controls.Add(_row);
}

public void BindRow(object sender, EventArgs e)
{
TableRow row = (TableRow)sender;
RepeaterItem container = (RepeaterItem)
row.NamingContainer;
DataRowView _dataRow = (DataRowView) container.DataItem;

StringBuilder sbKeyValuePairs = new StringBuilder();
for(int i=0;i < _dataRow.DataView.Table.Columns.Count;++i)
{
string columnName = _dataRow.DataView.Table.Columns[i].Caption;
if(i>0)
{
sbKeyValuePairs.Append(",");
}
sbKeyValuePairs.Append("'");
sbKeyValuePairsString.Append(columnName);
sbKeyValuePairs.Append("','");
sbKeyValuePairs.Append(Convert.ToString(_dataRow[i]));
sbKeyValuePairs.Append("'");
}
row.Attributes.Add("KeyValuePairs",sbKeyValuePairs.ToString());
row.Attributes.Add("ondblclick","javascript:webControl.Page.GetPostBackEventReference(webControl,"DblClick-" + _dataRow[0].ToString()) );

for(int i=0;i < row.Cells.Count;++i)
{
TableCell cell = (TableCell) row.Cells[i];
cell.Wrap = false;
string cellText = _dataRow[i].ToString();
try
{
DateTime dColumnValue = Convert.ToDateTime(cellText);
cellText = dColumnValue.ToString("yyyy-MM-dd");
}
catch{}
cell.Text = cellText;
}
}
}

//Our repeater is essentially a table (You can have very complex HTML here. We used table for simplicity)
public class MyHeaderTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
LiteralControl lcTABLE = new LiteralControl("");
container.Controls.Add(lcTABLE);
}
}

//As our repeater is a table we close it in the footer
public class MyFooterTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
LiteralControl lcTABLE = new LiteralControl("
");
container.Controls.Add(lcTABLE);
}
}

The following is the code in the custom control that assigns the above Templates to the repeater control.

protected override void CreateChildControls()
{
Controls.Clear();

Controls.Add(repeater);

repeater.HeaderTemplate = new MyHeaderTemplate();
repeater.ItemTemplate = new MyItemTemplate(dt,this);
repeater.FooterTemplate = new MyFooterTemplate();

// Prevent child controls from being created again.
ChildControlsCreated = true;

//call the parent method
base.CreateChildControls();
}

protected override void OnPreRender(EventArgs e)
{
// Populate the repeater control with the Items DataSet
repeater.DataSource=dt;
// Bind the data to the repeater
repeater.DataBind();

base.OnPreRender (e);
}

0 Comments:

Post a Comment

<< Home