Developer

Browse ListView data with .NET's DataPager control

Microsoft .NET 3.5’s DataPager control delivers a paging interface that is tied to the ListView control and communicates with its corresponding ListView control regarding user input. Tony Patton explains how you can use the DataPager control to page through ListView data.

Microsoft .NET 3.5 introduces the DataPager control, which delivers a paging interface that is tied to the ListView control. DataPager also communicates with its corresponding ListView control regarding user input. Here's an explanation of how you can use the DataPager control to page through ListView data.

DataPager's basic properties

You can easily add the DataPager control to a Web Form within Visual Studio. The paging interface appears wherever you place the DataPager control on the page. You may place it before or after the ListView control, as well as within its LayoutTemplate element.

The DataPager control has two basic properties for using it in its default state: PagerControlID and PageSize.

  • PagerControlID is the ID of the ListView control to which it is bound. This is the data that will be paged.
  • PageSize is the number of items and rows to display on each page. The paging interface will appear when/if the PageSize is exceeded.

I'll use the same data source (an XML file) from last week's article about the ListView control to demonstrate its usage:

<?xml version="1.0" encoding="utf-8" ?>

<sites>

<site id="1" url="www.techrepublic.com" title="TechRepublic" />

<site id="2" url="www.cnet.com" title="CNET" />

<site id="1" url="www.google.com" title="Google" />

<site id="2" url="www.gamespot.com" title="GameSpot" />

<site id="1" url="www.builder.com" title="Builder AU" />

<site id="2" url="reviews.cnet.com" title="Reviews" />

<site id="1" url="www.download.com" title="Downloads" />

<site id="2" url="www.cnetnetworks.com/" title="CNET Networks" />

</sites>

The following ASP.NET page contains ListView and DataPager controls to display and page through the data contained in the XML data source. The PageSize property is set to display only two items per page. In this example, the DataPager control displays the individual page links as numbers, along with the first and last buttons to view the first and last data pages.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebTest._Default" %>

<!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>TechRepublic.com - Working with DataPager control</title>
</head>

<body>

<form id="frmDataPager" runat="server">

<asp:DataPager ID="dpExample" runat="server" PagedControlID="lvExample" PageSize="2">

<Fields>

<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True"

ShowNextPageButton="False" ShowPreviousPageButton="False" />

<asp:NumericPagerField />

<asp:NextPreviousPagerField ButtonType="Button" ShowLastPageButton="True"

ShowNextPageButton="False" ShowPreviousPageButton="False" />

</Fields>

</asp:DataPager>

<br />

<asp:ListView ID="lvExample" runat="server" DataSourceID="XmlDataSource1">

<AlternatingItemTemplate>

url: <asp:Literal ID="litURL" runat="server" Text='<%# Eval("url") %>' />

<br />

title: <asp:Literal ID="litTitle" runat="server" Text='<%# Eval("title") %>' />

<br />

</li>

</AlternatingItemTemplate>

<LayoutTemplate>

<ul>

<div id="itemPlaceHolder" runat="server" />

</ul>

</LayoutTemplate>

<EmptyDataTemplate>

No data was returned.

</EmptyDataTemplate>

<ItemTemplate>

url: <asp:Literal ID="litURL" runat="server" Text='<%# Eval("url") %>' />

<br />

title: <asp:Literal ID="litTitle" runat="server" Text='<%# Eval("title") %>' />

</li>

</ItemTemplate>

<ItemSeparatorTemplate>

<hr>

</ItemSeparatorTemplate>

</asp:ListView>

<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/sites.xml" />

</form></body></html>

Customization

The DataPager control contains a Fields element (which is visible in the previous listing) that allows you to define the appearance of links to pages, previous/next pages, and first/last pages. The links may be buttons, a hyperlink, or an image.

The Fields element may contain one or more of the following elements:

  • NextPreviousPagerField: Provides buttons that enable users to navigate through the pages of data one page at a time or to jump to the first or last page of data. The element contains attributes for hiding, showing, and styling certain buttons.
  • NumericPagerField: Provides a way for users to jump to individual pages according to their page number within the data set. The element contains attributes for showing/hiding links and text, as well as styling what is displayed.
  • TemplatePagerField: Provides the most control, as you can define a custom template for displaying data.
Note: You are not restricted to using one instance of one or more of these elements within the DataPager control; you may choose to use multiple instances of the elements depending on your needs.

The following code snippet includes the source for an instance of the DataPager control that you may use with the previous example. The code uses the three elements within the Fields element of the DataPager control.

The NextPreviousPagerField element is set up to display buttons to access the first and last pages of the data. The NumericPagerField element is set up to display individual links to each page of data, as well as to allow the user to navigate through the data one page at a time via "Prev 2" and "Next 2" links.

The TemplatePagerField element adds a bit of customization to the paging interface. It uses C# to retrieve the total number of rows, the starting row number, and the overall page size to perform calculations. These calculations are used to display "(page x of xx)" text above the pager links and buttons. The TemplatePagerField element lets the user know where they are within the data.

<asp:DataPager ID="dpExample2" runat="server" PagedControlID="ListView1" PageSize="2">

<Fields>

<asp:TemplatePagerField>

<PagerTemplate>

<b>Page

<asp:Label runat="server" ID="CurrentPageLabel"

Text="<%# Container.TotalRowCount>0 ? (Container.StartRowIndex / Container.PageSize) + 1 : 0 %>" />

of

<asp:Label runat="server" ID="TotalPagesLabel"

Text="<%# Math.Ceiling ((double)Container.TotalRowCount / Container.PageSize) %>" />

(<asp:Label runat="server" ID="TotalItemsLabel" Text="<%# Container.TotalRowCount%>" />

records)

<br />

</b>

</PagerTemplate>

</asp:TemplatePagerField>

<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="true"

ShowNextPageButton="false" ShowPreviousPageButton="false" />

<asp:NumericPagerField PreviousPageText="< Prev 2" NextPageText="Next 2 >"

ButtonCount="10" />

<asp:NextPreviousPagerField ButtonType="Button" ShowLastPageButton="true"

ShowNextPageButton="false" ShowPreviousPageButton="false" />

</Fields>

</asp:DataPager>

These features of the DataPager control, along with the features for displaying data within the ListView control, allow you to build interfaces that meet every need.

Loading data

In response to last week's column, a couple of readers asked how the ListView control loads data. One caveat of the numerous data controls included with .NET is the default approach to loading data from backend data sources. That is, the controls load all data from the data source before displaying a subset on the page.

When paging through data (with or without the DataPager control), a server roundtrip is encountered for each paging request. The result is a performance hit for users; this is especially bothersome when you're dealing with larger data sets. AJAX provides one way to hide the server roundtrip.

The following ASP.NET page shows the ListView and DataPager controls placed within an AJAX-enabled page. It hides the page reloads from the user by requesting data in the background.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AJAXTest.aspx.cs" Inherits="WebTest.AJAXTest" %>

<!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>Ajax Test</title>

</head>

<body>

<form id="frmAjaxTest" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

<asp:UpdatePanel ID="UpdatePanel1" runat="server">

<ContentTemplate>

<asp:ListView ID="ListView1" runat="server" DataSourceID="XmlDataSource1">

<AlternatingItemTemplate>

<li style="">

url: <asp:Literal ID="litURL" runat="server" Text='<%# Eval("url") %>' />

<br />

title: <asp:Literal ID="litTitle" runat="server" Text='<%# Eval("title") %>' />

<br />

</li>

</AlternatingItemTemplate>

<LayoutTemplate>

<ul>

<div id="itemPlaceHolder" runat="server" />

</ul>

</LayoutTemplate>

<ItemTemplate>

<li style="">

url: <asp:Literal ID="litURL" runat="server" Text='<%# Eval("url") %>' />

<br />

title: <asp:Literal ID="litTitle" runat="server" Text='<%# Eval("title") %>' />

</li>

</ItemTemplate>

<ItemSeparatorTemplate>

<hr>

</ItemSeparatorTemplate>

</asp:ListView>

<asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1" PageSize="2">

<Fields>

<asp:TemplatePagerField>

<PagerTemplate>

<b>Page

<asp:Label runat="server" ID="CurrentPageLabel"
Text="<%# Container.TotalRowCount>0 ? (Container.StartRowIndex / Container.PageSize) + 1 : 0 %>" /> of
<asp:Label runat="server" ID="TotalPagesLabel"
Text="<%# Math.Ceiling ((double)Container.TotalRowCount / Container.PageSize) %>" />

( <asp:Label runat="server" ID="TotalItemsLabel" Text="<%# Container.TotalRowCount%>" /> records)<br /></b>

</PagerTemplate>

</asp:TemplatePagerField>

<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="true"

ShowNextPageButton="false" ShowPreviousPageButton="false" />

<asp:NumericPagerField PreviousPageText="< Prev 2"NextPageText="Next 2 >"

ButtonCount="2" />

<asp:NextPreviousPagerField ButtonType="Button" ShowLastPageButton="true"

ShowNextPageButton="false" ShowPreviousPageButton="false" />

</Fields>

</asp:DataPager>

<br />

<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/sites.xml">

</asp:XmlDataSource>

</ContentTemplate>

</asp:UpdatePanel>

</form></body></html>

While this may seem good for smaller data sets, it does not improve performance with regards to data requests. In my next column, I will examine another way to streamline data access so that only the desired records are loaded.

More options

The introduction of the ListView and DataPager controls with .NET 3.5 shows that Microsoft has listened to developers' complaints concerning display and paging functionality in other controls. The separation of paging functionality into the DataPager control provides more options for developers to build interfaces that allow users to navigate through data.

What features of .NET 3.5 excite you? Do you think the separation of paging into its own control is good? Share your thoughts with the Visual Studio Developer community.

Tony Patton began his professional career as an application developer earning Java, VB, Lotus, and XML certifications to bolster his knowledge.

---------------------------------------------------------------------------------------

Get weekly development tips in your inbox TechRepublic's free Visual Studio Developer newsletter, delivered each Wednesday, contains useful tips and coding examples on topics such as Web services, ASP.NET, ADO.NET, and Visual Studio .NET. Automatically subscribe today!

About

Tony Patton has worn many hats over his 15+ years in the IT industry while witnessing many technologies come and go. He currently focuses on .NET and Web Development while trying to grasp the many facets of supporting such technologies in a productio...

8 comments
Tony Hopkinson
Tony Hopkinson

of times I've had to solve this problem. Can't count one where I haven't had to do the streamlining as well! There are several things I like about .net 3.5, certain aspects of linq, the beefed up generics they had to implement it. Extensions. More by default inefficient cookie cutter widgets I can live without though. I'm one of those who's not mad keen on dataaware, even less so directly connected to a datasource. A middle layer, yes, if you keep control. Far too easy for you to start ending up with business logic in the presentaion layer and then you are D E A D dead in the water.

byeagle
byeagle

nested listviews like a master detail the use of dropdowns, check boxes and radio buttons using findcontrol for nested elements drag and drop between controls css styling using structured css dim the others while working on one record I look forward to your articles each week, many thank yous.

deepesh.bhatia
deepesh.bhatia

Good Functionality but i am concerned about the chunks of records and trips made to server for getting records by DataPager. Can u pls clear this thing that DataPager get whole data once in a single trip irrespective of page we are on, say for ex i want to view 2nd page and page size is of 10 records then on click will it go to db and get back 10 records or it will get whole records once like earlier it used to do in datagrid paging.

Justin James
Justin James

The DataPager looks like a good addition to the toolbox for people who use data binding. But I also know that a lot of people feel that things like this and the ListView are too many layers of abstraction on top of the data. How many layers of abstraction is too many, and is this past that line? J.Ja

Justin James
Justin James

My personal experience has been that I nearly always regret using the default data binding. But I never do the things that it was designed to do, either. If I were, I suspect that it is a real time saver. In fact, for the times where I did use it the way it was meant to be used, I liked it. I think the #1 biggest issue with data binding is that any system so free of its designer's assumptions that I can use it myself it going to be top heavy on configuration, to the point where configuring it is almost as much work as rolling my own (the code equivalent to buying and installing SAP). Anything that requires minimal configuration has too many assumptions in it and won't work for me. It's a no win situation. Nevertheless, I see lots of value for the typical developer in stuff like this. J.Ja

Tony Hopkinson
Tony Hopkinson

I can see some value to developer shops, in that as long as the assumptions are valid, cut scrape , set a few properties, pat self on back. What I see all too often though is some poor chump trying to work round those assumptions, to get that one extra bit of functionality. 99/100 you end up with something 'orrible. Worse still in my opinion, alot of them actually don't know or can't code an alternative. I pop a few 'queries' in an aggregate class, add a couple of events, and provide a populate method that takes a list box, and they consider that complicated? They should have a look under the hood at what .net is doing. Oh and there's a bug in the .net 2.0 version. If you have an onselectedchanged or onindexchanged event in the bound control, any exceptions it raises will be swallowed if it's bound.

Tony Hopkinson
Tony Hopkinson

Do not get me started... That one is my current bugbear.

Justin James
Justin James

... would be for the developers to push back when the 1 request would require a ton of work vs. just using the data bound control. I agree that they work OK when used "as is". Most of the mess occurs when trying to implement a feature with them that they do not support. J.Ja

Editor's Picks