AspdotnetCodes.com
Search
Articles
Books
Resources
Asp.Net News
Downloads
Free Tech Magazines
Asp.Net Web Hosting
Archives
Softwares
Newsletter
Suggest Us
Link to Us
Feeds Subscription
Articles
Questions & Answers
Tips & Tricks
 Asp.Net GridView Control Custom Sorting and Paging with Image Indicator
Posted by Moderator1 on 10/25/2008 8:10:19 AM Category: Asp.Net 2.0
Total Views : 119818
Add to my favorites
Email to friend
  
Introduction
This article takes pleasure in explaining the concept of custom sorting and custom paging of a GridView control in depth. We found numerous questions and forums that are speaking about GridView sorting with TemplateField columns. So we took the opportunity to explain the custom sorting of the GridView control in our own and simple way. Besides, that it explains how an Image can be toggled in the header row of the GridView control, to indicate which column is sorted and in which order (ascending or descending) it has been sort. By the way, to enhance the richness of the article we have added custom paging for the GridView control along with the custom Sorting. So you can sort the GridView control, navigate through the GridView pages, without sort order being reset.

For demonstration purpose, we are going to display Customer Information in a GridView control and we are going to perform sorting in the GridView control, which also got custom paging in it. So place a GridView control in the Aspx page, specify its AutoGenerateColumns="False". Then add TemplateFields columns to the GridView as many as columns you want to display. In our case, we are going to display Customer Name [Cus_Name], Gender [Cus_Gender], Age [Cus_Age], EmailId [Cus_Email] and State [Cus_State]. Every TemplateField column will contains a ItemTemplate section, AlternatingItemTemplate section, EditItemTemplate section, HeaderTemplate section and FooterTemplate section. For the purpose of this article, we are going to work on Only ItemTemplate and HeaderTemplate sections. And we will explain you, simply for only one TemplateField column, so that you can do the same for all columns in the GridView.

Point you MUST NOT DO

  • Don’t change the GridView’s AllowSorting property to True.
  • Don’t change the GridView’s AllowPaging property to True.
  • Don’t write any code in GridView’s PageIndexChanging event.
  • Don’t write any code in GridView’s Sorting event.
Concentrate in First TemplateField Column : Customer Name [Cus_Name]

In HeaderTemplate section, add a LinkButton, and change some of its properties as stated in the table below. The below table shows the property of the LinkButton, the value of the property you have to change and a brief note to explain the field's requirement.

Property Change as Note
ID lnkbtnCusName name of the LinkButton, must be unique for every LinkButton.
Text Name text to display at the Header row.
CommandName Sort actually this is the Command we need to execute. Keep this value unchanged for all the LinkButton controls in the Header row.
CommandArgument Cus_Name Customer Name Field Name in the Customer Table. Set this property accordingly for every column.

Next you have add a PlaceHolder control near the LinkButton control and specify its ID as ‘placeholderName’. You must assign unique ID for every PlaceHolders on each and every TemplateField columns.

Abstract Reminder:

You have to add a LinkButton and a PlaceHolder in each and every column of the TemplateField’s Header section that you want to do custom sorting and do the above-specified settings for every LinkButton and the PlaceHolder controls.

In the ItemTemplate section, add a Label control and bind its Text property to Customer Name [Cus_Name]. So the Label control in the ItemTemplate section of the GridView will look like, 

<asp:Label id="Label1" runat="server" Text='<%# Bind("Cus_Name") %>'>
</asp:Label>

Just repeat the above steps for all the columns you want to display in the GridView control as custom sorting column. As per our requirement, the GridView’s Html code will be as follows

<asp:GridView id="GridView1" runat="server"
OnRowDataBound="GridView1_RowDataBound"
OnRowCommand="GridView1_RowCommand"
AutoGenerateColumns="False" width="100%">
<Columns>

<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton id="lnkbtnCusName" runat="server" CommandName="Sort"
CommandArgument="Cus_Name">Name</asp:LinkButton>
<asp:PlaceHolder id="placeholderName" runat="server"></asp:PlaceHolder>
</HeaderTemplate>
<ItemTemplate>
<asp:Label id="Label1" runat="server" Text='<%# Bind("Cus_Name") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>

<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton id="lnkbtnGender" runat="server" CommandName="Sort"
CommandArgument="Cus_Gender">Gender</asp:LinkButton>
<asp:PlaceHolder id="placeholderGender" runat="server"></asp:PlaceHolder>
</HeaderTemplate>
<ItemTemplate>
<asp:Label id="Label4" runat="server" Text='<%# Bind("Cus_Gender") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>

<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton id="lnkbtnAge" runat="server" CommandName="Sort" CommandArgument="Cus_Age">Age</asp:LinkButton>
<asp:PlaceHolder id="placeholderAge" runat="server"></asp:PlaceHolder>
</HeaderTemplate>
<ItemTemplate>
<asp:Label id="Label5" runat="server" Text='<%# Bind("Cus_Age") %>'> </asp:Label>
</ItemTemplate>
</asp:TemplateField>

<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton ID="lnkbtnCusEmail" runat="server"
CommandArgument="Cus_Email" CommandName="Sort">Email Id
</asp:LinkButton>
<asp:PlaceHolder ID="placeholderEmail" runat="server"></asp:PlaceHolder>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("Cus_Email") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>

<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton id="lnkbtnCusState" runat="server" CommandName="Sort"
CommandArgument="Cus_State">State</asp:LinkButton>
<asp:PlaceHolder id="placeholderState" runat="server"> </asp:PlaceHolder>
</HeaderTemplate>
<ItemTemplate>
<asp:Label id="Label3" runat="server" Text='<%# Bind("Cus_State") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

Concentrate on designing of the Custom Paging

To create custom paging for the GridView control, we are going add a DataList control and name it as dlPaging. In its ItemTemplate section, add a LinkButton, name it as lnkbtnPaging. Set its CommandName property as lnkbtnPaging. Then choose End Template Editing and add two more LinkButton controls on either side of the DataList control. Name it as lnkbtnPrevious and lnkbtnNext and change its Text property as Previous and Next respectively. Better I suggest you to put an Html Table control and place these controls in it properly so that it will look nicely aligned. The Html source of these controls is given below.

<asp:LinkButton id="lnkbtnPrevious"
onclick="lnkbtnPrevious_Click" runat="server"> Previous </asp:LinkButton>

<asp:DataList id="dlPaging" runat="server"
RepeatDirection="Horizontal"
OnItemDataBound="dlPaging_ItemDataBound"
OnItemCommand="dlPaging_ItemCommand">
<ItemTemplate>

<asp:LinkButton ID="lnkbtnPaging" runat="server"
CommandArgument='<%# Eval("PageIndex") %>'
CommandName="lnkbtnPaging"

Text='<%# Eval("PageText") %>'></asp:LinkButton>

</ItemTemplate>
</asp:DataList>

<asp:LinkButton id="lnkbtnNext"
onclick="lnkbtnNext_Click" runat="server">Next</asp:LinkButton>
The LinkButton ‘lnkbtnPaging’ has to be binded with a DataSource to display page numbers. So bind its CommandArgument as ‘PageIndex’ and its Text property with ‘PageText’. The method to bind this DataList will be given and explained at the Code-Behind section, as doPaging method.

Code-behind Section

Declaration Section:

For the purpose of this article, we have collaborated both paging and sorting for a single GridView control. So every section of the source code explained below will cover both custom paging and sorting concept. Just concentrate bit more from here. For the purpose of custom paging, we are creating an instance of PagedDataSource class as follows

PagedDataSource pds = new PagedDataSource();

For maintaining the Page Index of the GridView control, we are going to maintain a ViewState variable called ‘CurrentPage’. It has to be declared and initialize as follows

public int CurrentPage
{

  get {
    if (this.ViewState["CurrentPage"] == null)
       return 0;
    else
       return Convert.ToInt16(this.ViewState["CurrentPage"].ToString());
  }

 set {
   this.ViewState["CurrentPage"] = value;
 }

}
Page Load Event:

In the Page Load event, we are going to bind the GridView with the data from the database using a private method called BindGrid.

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
     BindGrid(); 
  }
}


The complete source code for BindGrid method is explained below.

private void BindGrid()
{
  string sql = "Select * from Customer Order By Cus_Name";
  SqlDataAdapter da = new SqlDataAdapter(sql, “YourConnectionString”);
  DataTable dt = new DataTable();
  da.Fill(dt);
  DataView dv = dt.DefaultView;

  if (this.ViewState["SortExp"] != null)
  {
    dv.Sort = this.ViewState["SortExp"].ToString()
             + " " + this.ViewState["SortOrder"].ToString();
  }

  pds.DataSource = dv;
  pds.AllowPaging = true;
  pds.PageSize = 10;
  pds.CurrentPageIndex = CurrentPage;
  lnkbtnNext.Enabled = !pds.IsLastPage;
  lnkbtnPrevious.Enabled = !pds.IsFirstPage;

  GridView1.DataSource = pds;
  GridView1.DataBind();

  doPaging();
}


The above method fetches data from the Customer table, fill it in a DataTable, and set it to a DataView for purpose of Sorting and Paging concurrently. Next there is two ViewState variables such as SortExp and SortOrder, which stands for Sort Expression (the field to sort the GridView) and Sorting Order (Ascending or Descending order) respectively. Since the GridView works for sorting and paging concurrently, we have to maintain the Sort Expression and Sorting Order in the ViewState variables. So if the Sort Expression is available, then the DataView’s Sort property will be set with the ViewState’s SortExp and SortOrder values.

Next, we are binding PagedDataSource objects with the DataView, set its property AllowPaging to True, set its PageSize to 10, and initialize its CurrentPageIndex with our CurrentPage variable. By default CurrentPage will be 0. Then we set the Enabled property of the Previous and Next LinkButton controls with the PagedDataSource objects IsFirstPage and IsLastPage property. This is to make the Previous and Next LinkButton controls disable when the PageIndex reaches first and last page respectively.

Last, we bind the GridView control with PagedDataSource object to display the records and call another private method ‘doPaging’ for building custom Paging page numbers. The code for doPaging method is as follows

private void doPaging()
{
  DataTable dt = new DataTable();
  dt.Columns.Add("PageIndex");
  dt.Columns.Add("PageText");
  for (int i = 0; i < pds.PageCount; i++)
  {
     DataRow dr = dt.NewRow();
     dr[0] = i;
     dr[1] = i + 1;
     dt.Rows.Add(dr);
  }

  dlPaging.DataSource = dt;
  dlPaging.DataBind();
}


So the doPaing method has a DataTable with two columns such as PageIndex and PageText. The PageIndex column is the selected index value and PageText column is the display value in the dlPaging. So this DataTable has to be binded with dlPaging DataList control.

Source Code for Custom Sorting

In the GridView’s RowCommand event, we are going to do sort operation for the GridView control as follows


protected void GridView1_RowCommand(object sender,
GridViewCommandEventArgs e)
{
  if (e.CommandName.Equals("Sort"))
  {
     if (this.ViewState["SortExp"] == null)
     {
        this.ViewState["SortExp"] = e.CommandArgument.ToString();
        this.ViewState["SortOrder"] = "ASC";
     }
     else
    {
       if (this.ViewState["SortExp"].ToString() == e.CommandArgument.ToString())
       {
          if (this.ViewState["SortOrder"].ToString() == "ASC")
            this.ViewState["SortOrder"] = "DESC"; 
          else
            this.ViewState["SortOrder"] = "ASC";
       }
       else
       { 
         this.ViewState["SortOrder"] = "ASC"; 
         this.ViewState["SortExp"] = e.CommandArgument.ToString(); 
       }
    } 

       BindGrid();
  }
}
 
First we have to check the CommandName is equals “Sort” command, if so, we can initialize the ViewState variable “SortExp” with the CommandArgument (which contains the field name to sort) and “SortOrder” with “ASC” for ascending or “DESC” for descending order sorting. The above code got two conditions of assignment.

1. First time, the ViewState of SortExp will be nothing, so initialize it with the CommandArgument and set its SortOrder as “ASC”.

2. Next time, the ViewState of SortExp will have any field name, so we have to compare both the CommandArgument and the ViewState SortExp value.

  1. If both are same, then check the ViewState SortOrder contains value as “ASC” or “DESC”. If the value is “ASC”, then change the SortOrder value as “DESC” and vice versa.


  2. If both are not same, the keep the SortOrder as “ASC” and change the ViewState of SortExp to the new CommandArgument.

After all the checking and assignment, call the BindGrid event to re-arrange the GridView rows according to the above specified Sort Expression and Sort Order.

Source Code for Image Indicator in Header Row

The specialty of this article is an Image Indicator in the header row, indicates which column has sorted and in which order it has been sorted. We are going to do the coding in the GridView control RowDataBound event as follows.

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
 if (e.Row.RowType == DataControlRowType.Header
     && this.ViewState["SortExp"] != null)
   {
     Image ImgSort = new Image(); 
        if (this.ViewState["SortOrder"].ToString() == "ASC") 
                ImgSort.ImageUrl = "~/Images/downarrow.gif"; 
        else 
                ImgSort.ImageUrl = "~/Images/uparrow.gif";

 switch (this.ViewState["SortExp"].ToString())
 {
  case "Cus_State":
    PlaceHolder placeholderState = (PlaceHolder)
                                               e.Row.FindControl("placeholderState");
    placeholderState.Controls.Add(ImgSort);
    break;

case "Cus_Email":
    PlaceHolder placeholderEmail = (PlaceHolder)
                                               e.Row.FindControl("placeholderEmail"); 
    placeholderEmail.Controls.Add(ImgSort); 
    break;

case "Cus_Name": 
    PlaceHolder placeholderName = (PlaceHolder)
                                               e.Row.FindControl("placeholderName"); 
    placeholderName.Controls.Add(ImgSort); 
    break;

case "Cus_Sex": 
    PlaceHolder placeholderGender = (PlaceHolder)
                                            e.Row.FindControl("placeholderGender");         
    placeholderGender.Controls.Add(ImgSort); 
    break;

case "Cus_Age": 
    PlaceHolder placeholderAge = (PlaceHolder)
                                         e.Row.FindControl("placeholderAge"); 
    placeholderAge.Controls.Add(ImgSort); 
    break;
 }
}
}

The explanation for the above code is pretty simple. In the RowDataBound event’s Header row part, we have two sections, one for identifying the sort order and other for indicating the sort expression column. So we create an Image control at run-time and based on the SortOrder, we set the ImageUrl property. If the SortOrder is “ASC”, then set the ImageUrl with a down arrow image and for “DESC” SortOrder, set the ImageUrl with an up arrow image. Next based on the SortExp, we find the PlaceHolder control that is placed beside the LinkButton, and add the Image control into it. Thus, when the user clicks on the Header row LinkButton, the GridView will be sorted and an image will appear near the LinkButton and indicates that clicked column is sorted in Ascending or Descending order.
Source Code for Custom Paging

We have already completed the designing part of the Custom Paging for the GridView control. The DataList dlPaging will display page numbers. When it is clicked, the corresponding page will be appeared in the GridView control without disturbing the Sorting. For this we have to write code at the dlPaging ItemCommand event as follows

protected void dlPaging_ItemCommand(object source, DataListCommandEventArgs e)
{
  if (e.CommandName.Equals("lnkbtnPaging"))
  {
    CurrentPage = Convert.ToInt16(e.CommandArgument.ToString());
    BindGrid();
  }
}


Here we just set the CurrentPage value from the CommandArgument, which is actually the PageIndex, then call the BindGrid event. Thus we have integrated the DataList and the GridView control to perform Custom Paging.

To highlight the selected Page Number (PageIndex) in different style, do the following code in ItemDataBound event of the dlPaging datalist.

protected void dlPaging_ItemDataBound(object sender, DataListItemEventArgs e)
{
  LinkButton lnkbtnPage = (LinkButton)e.Item.FindControl("lnkbtnPaging");
  if (lnkbtnPage.CommandArgument.ToString() == CurrentPage.ToString()) 
  {
    lnkbtnPage.Enabled = false;
    lnkbtnPage.Font.Bold = true; 
  }
}


Source Code for Next and Previous LinkButton controls

When Next LinkButton is clicked, we have to increment the CurrentPage value and when Previous LinkButton is clicked, we have to decrease the value of the CurrentPage variable, then call the BindGrid method to display the records in the corresponding page.


protected void lnkbtnNext_Click(object sender, EventArgs e)
{
  CurrentPage += 1;
  BindGrid();
}

protected void lnkbtnPrevious_Click(object sender, EventArgs e)
{
  CurrentPage -= 1;
  BindGrid();
}


Since we are maintaining the Sort Expression, Sort Order and Page Index in the ViewState of the Page, Custom Sorting and Custom Paging is easily achievable at the same time, without one disturbing the other.

Now, save the changes you have done and run this page in the browser. For sure, the GridView control will be populated with data, if the records are more than 10, paging numbers will appear. When you click the any LinkButton in the GridView Header Row, GridView will re-arrange the records in Ascending Order, and an image with down arrow will appear in the header row of that column. Click the same LinkButton again, now the GridView will re-arrange the records Descending Order and the image will show an up arrow denotes it is descending order. Click on the page number, you can see the GridView navigates to the page number you clicked without the Sorting being disturbed.

This article is to give you an abstract idea of doing custom paging and sorting in GridView control. There will be many ways to do this. It is up to you, to choose the right one, that suite your requirement.

Wanna play with our Custom Sorting and Paging GridView control, click here.
You need to Login or Register to download Source Code.
 
Viewer's Comments
Posted by Mr Quach on 11/13/2008 6:25:53 PM
Nice code. Thanks you so much!
 
Posted by Nat on 11/17/2008 9:31:43 AM
Thanks.
 
Posted by dhiresh on 11/24/2008 6:14:58 AM
Thank you so much . 1)can you tell me Enablesortingandpagingcallback property use in templatedField or bound fileld or without sqldatasource 2)how gridview sorting & paging using javascript
 
Posted by Akhilesh on 1/26/2009 7:16:02 AM
yeah, Its very usefull , Thanks
 
Posted by Kumar on 1/26/2009 5:18:17 PM
Thanks. Excellent Article
 
Posted by Emmanuel on 2/8/2009 7:49:26 AM
Great article ... But how bout if the gridview/datalist created dynamically using itemplate?is there a problem with the ajax update panel?
 
Posted by Emmanuel on 2/10/2009 2:04:23 AM
is this gridview and datalist (paging) can be made dynamically? thanks alot
 
Posted by Krys on 2/10/2009 1:21:16 PM
Good job. Clear and simple explanation.
 
Posted by Bob MacNeel on 2/25/2009 1:43:04 PM
I've been trying for over a month to get custom paging working with a gridview with no success, but I got yours working on my data quickly and easily. Thanks very much for the great article. The only addition I need is how to reduce the page numbers from being spread across the page when there is a large number of records returned, for example 1,2,3, 99,100, etc I would like 1-10... 11-20, etc. Can you please provide the code to do this?
 
Posted by shriya on 2/26/2009 4:07:00 AM
stupid answer
 
Posted by Phan Van Truong on 3/31/2009 1:13:42 PM
Thanks so much !
 
Posted by Ahmad on 5/11/2009 2:39:43 PM
thank you
 
Posted by Ahmad on 5/15/2009 5:33:52 AM
I've been trying for over a month to get custom paging working with a gridview with no success, but I got yours working on my data quickly and easily. Thanks very much for the great article. The only addition I need is how to reduce the page numbers from being spread across the page when there is a large number of records returned, for example 1,2,3, 99,100, etc I would like 1-10... 11-20, etc. Can you please provide the code to do this?
 
Posted by aquarian on 6/2/2009 1:10:42 AM
In case of any command in header, gridview onrowcommand is never fired. Am I missing something???
 
Posted by Nripin on 6/24/2009 3:59:53 AM
With a few mods this is near perfect :) great code mate !!!!!!
 
Posted by Guna on 6/24/2009 5:21:26 AM
Its a good article.. But i implement this code ..It is not worked..(ie) when i click sorting/paging it will bound two times..please reply what i m mistake. Thanks, Guna Sundari.
 
Posted by monsit kamsoy on 7/13/2009 5:34:37 AM
Good...
 
Posted by Dean on 8/11/2009 10:08:54 AM
Nice 1. This is cool. Really very good. Thanks!
 
Posted by sch on 8/24/2009 4:57:33 AM
This was very helpful. Thank you.
 
Posted by Sruthi Ponguluru on 8/25/2009 11:23:59 AM
Thanks........
 
Posted by Samarjeet Singh on 8/27/2009 7:47:26 AM
Thnks for this code, very nice code Thnks a Lot........
 
Posted by ravikiran on 8/28/2009 7:28:47 AM
Excellent article. It helped me alot.
 
Posted by Chandralekha on 9/16/2009 7:04:23 AM
Thank You!! for your article, it helped me a lot, this sort of sorting is what i was looking for..
 
Posted by SP on 10/30/2009 1:51:04 AM
Excellent article, very helpful for beginers. Thanks.
 
Posted by Saritha on 11/10/2009 5:44:39 AM
Nice Code its working fine and dataview sort is so nice thanks alot
 
Posted by Piyush on 12/22/2009 12:27:10 AM
Awesome article. Good description, everything point wise. really liked it. Thank you so much.
 
Posted by Waran on 1/4/2010 1:05:33 AM
hi i download the your source code but there is a issue controls are not found please help me
 
Posted by thiago on 1/6/2010 9:58:08 AM
how do i access the controls inside the ItemTemplates in the GridView? I have tried using GridView1.FindControl("controlId") but it does not find the DataList and LinkButton controls? any ideas?
 
Posted by Arsalan on 1/15/2010 6:37:28 AM
nice article...
 
Posted by amr on 2/1/2010 4:01:13 AM
really its a very nice one but there is a problem when I use GridView1_RowDeleting and delete the last recored in the last page the page numbers still appear and if you click on the last page number it throws System.IndexOutOfRangeException: Index 4 is either negative or above rows count.
 
Posted by dhawal Seth on 7/20/2010 6:48:48 AM
Thanks a ton.. you saved lot of time. Keep up the good work
 
Posted by sajjad on 11/30/2010 6:44:33 AM
Thanks Dear for share his knowledge.very helpfull
 
Posted by Akash on 3/1/2011 2:45:30 AM
Excellent code man... :)
 
Posted by Akash Saikia on 3/1/2011 2:46:23 AM
It helped me alot in my project
 
Posted by BAN on 5/26/2011 2:01:48 AM
Excellent job...Simple to understand...Thanks for your post
 
Posted by Balaji on 9/15/2011 8:51:24 AM
Informative
 
Posted by lubsi on 8/27/2012 12:24:03 AM
This does not help in improving the performance of the application in any way. You are actually loading the entire data in the datatable and then performing the sorting and paging which adversely affects the performance when dealing with large amount of data.
 
Posted by Ankit Jindal on 11/15/2012 6:15:58 AM
Custom Sorting section is written beautifully. Really very informative and good one. Thanks, Ankit
 
Posted by Daniel Fitzgerald on 12/6/2012 10:31:39 AM
Very good article. Thank you.
 
Posted by John on 12/6/2012 5:01:42 PM
Excellent Article - Love the points you must not do. I had GridView’s AllowSorting property to True and was getting an error. Re-read the article and got it "sorted"!! :)
 
Posted by popo on 1/9/2013 4:02:21 AM
Nice One ... save my lot of dizzy time thank ...
 
Posted by sajeeth on 5/19/2013 3:25:24 AM
Greate work.
 
Posted by JaiGanesh on 5/9/2014 9:48:21 PM
Nice
 
 Rating & Comments
A word 'Excellent' means lot to the author of this article. You can give comments about this article but not the author.
Rate this Article:
Name:
Email Id:  
We never display your email id anywhere.
Comment/Question: Max. 500 letters
Two plus Fifty Equals To
 
 
Sponsored by
Website Magazine
SearchSAP
The ASP.NET 2.0 Anthology: 101 Essential Tips, Tricks & Hacks - Free 156 Page Preview