Paging In DataList Control
|
|
|
|
|
Downloads
If you are seeing this section and do not see download links, this means that you are not logged into our site. If you already are a member, click on the login link
and login into site and come back to this page for downloading the control files. If you are not a member, click on registration link to
become a Winista member and download the control for free.
ASP.Net provides a very generic but very flexible DataList where you can control the apperance of each
item in your data source. This control lacks a very useful feature of paging. Recently for development of
product collection page on Pardesi Fashion site we
needed to use DataList control. But the product data set was so large that we had no choice to figure out
how we are going to do paging to display all the data. This article is explanation of that implementation
and we have attached a scaled down version of that implementation as sample project with this article.
Since there is no built in support for paging in DataList that means we have to maintain the curent page index and
page index is user asking for. There could be two ways to keep track of this parameter. One would be to handle
server side events when user clicks on the pager links and then keep track of the index number. And second would be
to pass page index parameters in query string. I prefer using the later approach because it gives an advantage in better
search engine optimization (SEO) of your pages. When each pager link is a different URL the search engine gets to spider
each page for that dataset.
Implementation
The control is declared on the page as usual DataList controll. To implement paging we added two Panel controls, one
at the top of the list and one at the bottom.
<asp:Panel ID="TopPager_Panel" runat="server" BackColor="AliceBlue"
BorderWidth="1" BorderStyle="Dashed"></asp:Panel>
<div>
<asp:DataList ID="Paging_DataList" runat="server" RepeatDirection="Horizontal"
RepeatColumns="2" BackColor="White" BorderColor="#CC9966" BorderStyle="None"
BorderWidth="1px" CellPadding="4" GridLines="Both">
<ItemTemplate>
<div>
<span><b>SKU:</b></span> <span><%#Eval("SKU") %></span>
</div>
<div>
<span><b>Name:</b></span> <span><%#Eval("Name") %></span>
</div>
</ItemTemplate>
</asp:DataList>
</div>
<asp:Panel ID="BottomPager_Panel" runat="server" BackColor="AliceBlue"
BorderWidth="1" BorderStyle="Dashed"></asp:Panel>
The pager links were built by adding Hyperlink controls at run time inside the Panel controls
based on total pages that needed to be displayed.
private void BindPager()
{
if (_totalPages <= 1)
{
TopPager_Panel.Visible = BottomPager_Panel.Visible = false;
return;
}
TopPager_Panel.Visible = BottomPager_Panel.Visible = true;
for (int i = 0; i < _maxPagesInPager; i++)
{
HyperLink topLink = new HyperLink();
HyperLink bottomLink = new HyperLink();
LiteralControl topLiteral = new LiteralControl(" ");
LiteralControl bottomLiteral = new LiteralControl(" ");
topLink.Text = bottomLink.Text = (i + 1).ToString();
if (_pageIdx != (i + 1))
{
topLink.NavigateUrl = bottomLink.NavigateUrl =
String.Format("~/Default.aspx?pageidx={0}", i + 1);
}
TopPager_Panel.Controls.Add(topLink);
TopPager_Panel.Controls.Add(topLiteral);
BottomPager_Panel.Controls.Add(bottomLink);
BottomPager_Panel.Controls.Add(bottomLiteral);
}
}
Aa you can notice from the code snippet above that each pager link passes the page index
in query string parameter. This parameter is used to get appropriare slice of the data to
bind to the control.
The main part of the implementation is how to get slice of data that will be used to bind with
DataList control. There are 2 approaches you can take in this.
- First approach will be to take advantage of new ROW_NUMBER function in Sql Server 2005 where
you can specify in your select statement start and end row index numbers in the dataset. Here is
and example from Sql Server 2005 documentation.
USE AdventureWorks;
GO
WITH OrderedOrders AS
(SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (order by OrderDate)as RowNumber
FROM Sales.SalesOrderHeader )
SELECT *
FROM OrderedOrders
WHERE RowNumber between 50 and 60;
The advantage of this approach will be that it saves you trouble of caching the whole result set and
then slicing it up as nneded. The drawback of this approach is that it puts a dependency on your
solution on using Sql Server 2005 which may or may not be an option all the time.
-
Second approaach will be to get slices of the data from your result set and bind that to your control.
This approach requires you to fetch the full set before hand and then extract slices from it. But it
frees you from dependencies on underlying technologoies. And we took this approach because we host
our solutions on different type of database servers.
private void GetProductsFromDatabase()
{
SqlConnection conn = new SqlConnection(Products_DataSource.ConnectionString);
SqlDataAdapter sqlda =
new SqlDataAdapter(new SqlCommand(Products_DataSource.SelectCommand, conn));
_productsDataSet = new DataSet("products_set");
sqlda.Fill(_productsDataSet);
_productsList = new List<Product>();
foreach (DataRow dr in _productsDataSet.Tables[0].Rows)
{
Product prod = Product.LoadFromDataRow(dr);
_productsList.Add(prod);
}
}
private List<Product> GetProductsListForPage(int pageIdx, int pageSize, List<Product> srcList)
{
int start = pageIdx * pageSize;
int end = start + pageSize;
if (end > srcList.Count - 1)
{
end = srcList.Count - 1;
}
List<Product> slicedList = new List<Product>();
for (int i = start; i < end; i++)
{
slicedList.Add(srcList[i]);
}
return slicedList;
}
Sample Project
The attached sample was created in Visual Studio 2008. We did not use any API from .Net 3.5 or things like that.
So if you want to simply port the code over to Visual Studio 2005 or Visual Studio 2003 project, simple copy the
page and code file in your project and you should be good to go.
|