|
|
|
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 :
38872 |
|
Adding to your Favorites....
|
|
|
 |
|
|
|
|
|
|
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.
- 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.
- 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|