Introduction
In order to create a dynamic page, we need some server side control to do repetitive work and create the page. There are lots of controls provided by Microsoft .NET, i.e. DataList
, DataGrid
, GridView
, Repeater
and many more.
Background
I love to use Repeater as it is light weight and if I need it only for showing data. One of the drawbacks of using Repeater is that it does not have in-built functionality for Paging and Sorting. This article will be helpful to people who need a light weight control and also want to use Paging and Sorting.
This article will show you how to implement Paging and Sorting in the Repeater. I also have a working demo for you. You can download it form here.
Using the Code
We are going to use the following features and class:
PagedDataSource
: This class encapsulates all the properties for paging of a data-bound control which allows it to perform paging. This class is sealed so there is no inheritance. - Repeater: A light weight data-bound control which allows us to create dynamic data using custom layout without Paging support.
- Extension Methods: One of the cool functionalities of C# 3.0, allows us to create our own methods on already existing class without inheritance. You can find more on Extension methods here. We will use few extension methods for sorting.
First we should create a data source to which we are going to assign PagedDataSource
object. Let's create one public
property named UserList
by generating some random values.
IList<UserInfo> list;
for (int i = 1; i <= 100; i++)
{
list.Add(new UserInfo()
{
FirstName = string.Format("First Name : {0}", r.Next(6 * i, 60 * i + 3)),
LastName = string.Format("Last Name : {0}", r.Next(11 * i, 60 * i + 7)),
Password = string.Format("Password : {0}", r.Next(13 * i, 60 * i + 11)),
UserName = string.Format("UserName : {0}", r.Next(17 * i, 60 * i + 23)),
LastLoginDate = DateTime.Now.AddMinutes(r.Next(7 * i, 12 * i + 13)),
});
}
return list;
We have a data source ready with us, the next step will write FillRepeater
method which creates an object of PagedDataSource
set DataSource
property. Along with that, we have to set AllowPaging
properties, which indicate whether paging is enabled in data-bound or not.
PagedDataSource objPds = new PagedDataSource();
objPds.DataSource = UserList;
objPds.AllowPaging = true;
objPds.PageSize = 7;
lbtnPrev.Enabled = !objPds.IsFirstPage;
lbtnNext.Enabled = !objPds.IsLastPage;
rptUsers.DataSource = objPds;
rptUsers.DataBind();
While doing paging, we always need to take care about lower bound and upper bound; to have navigation, PagedDataSource
provides two getter properties IsFirstPage
and IsLastPage
, which allow you to track your navigation. Let's create handlers for Next and Previous buttons.
protected void lbtnPrev_Click(object sender, EventArgs e)
{
NowViewing--;
FillRepeater();
}
protected void lbtnNext_Click(object sender, EventArgs e)
{
NowViewing++;
FillRepeater();
}
NowViewing
is the property which maintains the current viewing page into viewstate
:
public int NowViewing
{
get
{
object obj = ViewState["_NowViewing"];
if (obj == null)
return 0;
else
return (int)obj;
}
set
{
this.ViewState["_NowViewing"] = value;
}
}
We are done with simple Paging with repeater. Here is the output for simple paging:
You can also add First and Last link, IsFirstPage
and IsLastPage
can help you to manage the visibility for links.
lbtnFirst.Enabled = !objPds.IsFirstPage;
lbtnLast.Enabled = !objPds.IsLastPage;
Also you can set the viewing message by using NowViewing
property and PageCount
of PagedDataSource
.
lblCurrentPage.Text = "Now viewing : " + (NowViewing + 1).ToString() +
" of " + objPds.PageCount.ToString();
For pager, you just need to set PageSize
property.
objPds.PageSize = int.Parse(ddlPageSize.SelectedValue);
Following is the image which will show how the page will look like after adding pager, now viewing message, first and last link.
So far so good, now let's add a sorting feature to our page. We are going to use Extension Methods a cool feature of C# 3.0. I created the following 5 extension methods to implement the sorting.
public static IList<UserInfo> OrderByLastLoginDate
(this IList<UserInfo> userList, bool isAscending)
public static IList<UserInfo> OrderByPassword
(this IList<UserInfo> userList, bool isAscending)
public static IList<UserInfo> OrderByLastName
(this IList<UserInfo> userList, bool isAscending)
public static IList<UserInfo> OrderByFirstName
(this IList<UserInfo> userList, bool isAscending)
public static IList<UserInfo> OrderByUserName
(this IList<UserInfo> userList, bool isAscending)
The first argument is list and another is IList<UserInfo>
and the other is isAscending
, which decides the order. Each of these methods are using Lambda expression and two extension methods OrderBy
and OrderByDescending
. Let's look into one of the methods.
public static IList<UserInfo> OrderByUserName
(this IList<UserInfo> userList, bool isAscending)
{
if (isAscending)
return userList.OrderBy(a => a.UserName).ToList();
else
return userList.OrderByDescending(a => a.UserName).ToList();
}
We created extension methods for sorting, let's use those methods to get sorting done.
We are going to use two viewstate
objects ViewState["SortExpression"]
which stores the sort expression and ViewState["SortDetails"]
which is Hashtable
to store sort order for field. After applying some logic, we can finally have sortExpression
to identify on which field we need sorting and isAscending
which is used to decide order. Based on this information, the following code will call extension method which does the sorting and binds the data to PagedDataSource
.
switch (sortExpression)
{
case "UserName":
return list.OrderByUserName(isAscending);
case "FirstName":
return list.OrderByFirstName(isAscending);
case "LastName":
return list.OrderByLastName(isAscending);
case "Password":
return list.OrderByPassword(isAscending);
case "LastLoginDate":
return list.OrderByLastLoginDate(isAscending);
default:
return list.OrderByUserName(isAscending);
}
Simple right? Ok, so we are done with sorting too.
Points of Interest
Use of Extension method helps to write smart code, also the PagedDataSource
is flexible for sorting and paging.
History
- 14th July, 2009: Initial post
- 15th July, 2009: Article updated