Up till recently I’ve been very suspicious of the higher level tools that ASP.Net 2.0 offers. Site Map, Menu controls, the dreaded Web Parts. Be a man – write it yourself. This even stretched to a refusal to use the DataGrid and related controls. I can do better with a small screwdriver and a dynamic control collection. And for years I stuck to that.
Recently though I’ve been working in an environment where they are big fans of Microsoft controls, so as a wise man once said ‘When in Rome use the same ASP.Net controls as the Romans do’. With that in mind I have been getting my hands dirty with DataGrids, DataViews and Repeaters. One of the things that has always put me off of these controls is which control do you use for what. The confusion was so great that often I had 2 or 3 different controls on a page at one time to compare, contrast and moan about. The result of all this moaning/development was
- For paging – use a DataGrid
- For an easy primary key for each row – use a DataGrid
- For multiple columns – use a DataView
- For fine control over what is displayed on each cell – Moan a lot then go back to using a dynamic collection of TableCells (that designers will never, ever be able to see).
But then as I was walking on the road to Damascus (a local falafel shop) a bright light shone from the clouds and a wise voice spake unto me and said “don’t mess around with all those other controls – just use Repeaters”. Thus and verily I journeyed back to the promised land and recoded all my grids with repeaters using the following divinely inspired techniques to get over the aforementioned limitations.
Primary Key for each Row
Use a hidden field (i.e. label with visibility set to false) and write the value into that
<asp:Repeater runat="server">
<ItemTemplate>
<asp:Literal ID="lblPrimaryKey" runat="server" Visible="false"
Text='<%# DataBinder.Eval(Container.DataItem, "PrimaryKeyId") %>' />
<%# DataBinder.Eval(Container.DataItem, "Name") %>
<%# DataBinder.Eval(Container.DataItem, "Address") %>
<%# DataBinder.Eval(Container.DataItem, "DoB")%>
</ItemTemplate>
</asp:Repeater>
Once written in the primary key can be accessed through the event handlers of the data grid – see below.
protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e)
{
Control lblKey = item.FindControl("lblPrimaryKey");
Int primaryKey = Int32.Parse(lblKey.Text);
//do something with the primary key
};
Multiple columnsUse divs for the columns and float them to the left (see
http://css.maxdesign.com.au/floatutorial/ for float tutorial). The below code shows it in action.
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<div style="width:800px;">
</HeaderTemplate>
<ItemTemplate>
<div style="width:200px;float:left;">
<%# DataBinder.Eval(Container.DataItem, "DisplayField")%></div>
</ItemTemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
The above example gives 4 columns i.e. 800px box surrounding the repeater with divs of 200px floated inside – sooo only 4 can fit before a new row is started. Obviously you don’t need to be a maths genius to work out the numbers for other numbers of columns (e.g. 600px outside, 200px divs – 3 columns etc…).
Fine control over each cell
If you have a requirement to modify each cell depending on the primary key of the row – leverage the On_ItemDataBound event of the repeater grid and modify the contents of each cell as it’s rendered
<asp:Repeater ID=" Repeater1" runat="server"
OnItemDataBound="Repeater1_ItemCreated">
<ItemTemplate>
<asp:Literal ID="lblPrimaryKey" runat="server" Visible="false"
Text='<%# DataBinder.Eval(Container.DataItem, "PrimaryKeyField")%>' />
<%# DataBinder.Eval(Container.DataItem, "Name") %>
<%# DataBinder.Eval(Container.DataItem, "Address") %>
<asp:Button ID="btnGo" runat="server" Text="Details" />
</ItemTemplate>
</asp:Repeater>
The below event is fired when the grid is rendered
protected void rptSurveyListNao_ItemCreated(object sender,
RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item
e.Item.ItemType == ListItemType.AlternatingItem)
{
Control lblSurveyStatus = item.FindControl("lblPrimaryKey");
Int primaryKey = Int32.Parse(lblSurveyStatus.Text);
If(primaryKey > 0)
{
btnGo = (Button)item.FindControl("btnGo");
btnGo.Enable = true;
}
}
}
It the above example we could control the button activity based on the primary key in the repeater row.
PagingUse the PagedDataSource following the technique outlined in
4GuysFromRolla. . OK hands up for this one – I’ve never used it but I’ve been assured by real life people that it works
And from that day forward all the HTML coders and designers in the land
came to pay homage to the lowly Repeater because they could easily access the
HTML tags behind the controls and not struggle with the arcane DataGrid styling
properties.