The ListView Dominates The Repeater
(
Aug 07 2007 - 07:43:15 AM by
Timothy Khouri) - [
print article]
The Repeater control that was introduced with the dawn of ASP.NET encapsulated much needed functionality and has given web developers a customizable, object oriented way of repeating any kind of data (that doesn't belong in a table which is handled by the GridView control). But the new ListView control in ASP.NET 3.5 blows the Repeater control out of the water. This article will discuss the differences between the two controls showing all the powerful features of the ListView control.
The need to "repeat" some HTML data is in almost every dynamic website out there. Every blog (whether written in .NET, PHP, ColdFusion or whatever), every RSS feed and every forum is an example of the need to 'spit out' the same HTML template over and over again, just changing some of the details inside. In my PHP days, I would have to write a 'for loop' and bounce between 'echoing' HTML strings and PHP variables. This is the farthest thing from clean code, object oriented programming or anything that I ever want to do again (and if you don't know what I'm talking about, then be happy... that's like not being able to relate to grandpa's war stories).
The Repeater control allowed you to describe a header and footer template (to specify what HTML should come above and below the list of 'items' that are going to be repeated) and an "item" template (to specify the HTML and server controls that will be used for every item in the enumerable data items that you are bound to). It also has support for an "empty item template" so that you can render some default HTML to the client if the data source that your repeater is bound to happens to be empty. That gives you enough functionality to get the job done, but it still falls down in a few key areas.
Problems with the Repeater
First of all, the notion of a 'header' and 'footer' template is no better than the old PHP (or "classic" ASP) way of doing things. It's not really object oriented, but rather it bares the ignorance of "well, I'm just sending HTML to a web browser", instead of the concept of building objects (that happen to render HTML to a web browser in most cases). The new ListView control steps up to the plate by removing the header/footer templates and instead you use a single LayoutTemplate.
You might be wondering "How does a single template give you the ability to achieve both a header and a footer?" Well, in the LayoutTemplate you can specify a server control (yes, an object!) that will be used as a parent control for each item in the ItemTemplate control from there on. This will make a lot more sense if you look at some code, so let's look at an example of a Repeater control and a ListView control. For now, we'll show the how to achieve the same functionality between the two. Here's the code:
<asp:Repeater ID="MyRepeater" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<%#Eval("SiteAddress") %></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ListView ID="MyListView" runat="server">
<LayoutTemplate>
<ul>
<asp:PlaceHolder ID="itemContainer" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<%#Eval("SiteAddress") %></li>
</ItemTemplate>
</asp:ListView>
You should right away see the difference between the two. The fact that you have to break up the "ul" tag in the Repeater is nasty. In fact, it's not even valid HTML. Whereas if you look at the clean, object oriented way of achieving the same thing with the ListView, the code seems a lot nicer. You might be wondering how the ListView knows to look for a control with the ID of "itemContainer". This is nothing magical, but rather it's the default server control ID it will look for (so you can change it to look for something else by changing the ItemContainerID property).
Just to put your mind at ease, both of these above controls will render almost the exact same HTML. Here is what they both look like (which you can see for yourself in the attached source files at the end of the article):
The Forgetful Repeater
Another major failing of the Repeater control (and this is probably the biggest one) is that you couldn't save/tap into the data you have bound later (whether in an ItemCreated event, or after a post-back etc). This means that if you wanted to use some values that were in the data source that your repeater was bound to, you would have to store it in memory, store and retrieve the values in the ViewState yourself or re-hit your data source every time you wanted to get these values.
The ListView control once again comes to the rescue with the added "DataKeyNames" property (just like the GridView control has in ASP.NET 2.0). This example will show how you can store some values in the DataKeys section of the ListView and retrieve them back later. We'll make another list of websites, but this time they are going to be LinkButtons that, when clicked on, will display the website's "description" on the page. Here's the code:
<asp:ListView ID="MyListView" runat="server" DataKeyNames="WebSiteName,Description">
<LayoutTemplate>
<ul>
<asp:PlaceHolder ID="itemContainer" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<asp:LinkButton ID="SiteLink" runat="server" /></li>
</ItemTemplate>
</asp:ListView>
<p id="SelectedSiteDescription" runat="server" />
private void MyListView_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
ListViewDataItem currentItem = (ListViewDataItem)e.Item;
DataKey currentDataKey = this.MyListView.DataKeys[currentItem.DataItemIndex];
LinkButton SiteLink = (LinkButton)currentItem.FindControl("SiteLink");
SiteLink.Text = (string)currentDataKey["WebSiteName"];
SiteLink.Click += delegate
{
this.SelectedSiteDescription.InnerText = (string)currentDataKey["Description"];
};
}
}
That's a Wrap
From what we've seen alone, the ListView is the right choice for anything the old Repeater control could do. On top of that, the added functionality of the DataKeyNames and the object-oriented style of the LayoutTemplate make it all that much more appealing. However, there is another piece of functionality that is brought to you by the ListView that has been a long time coming in the ASP.NET world, and will be very well received - pagination.
Yes, the ASP.NET 2.0 GridView control has pagination, but that's only for tabular data (things that look like an Excel file). But the new DataPager control allows you to extend the ListView's functionality to utilize pagination as well. That functionality will be discussed in future articles.
The source code I used in the article was written in Visual Studio 2008 Beta 2. You can download it here: SingingEels_ListView_VS_Repeater.zip