Tuesday, October 4, 2011

GridView Paging and Sorting

I just want to share how I make my paging and sorting in C#.  I had made a lot of styles before but this is the one that I used most, so in all of my Grid Views, here is what I do.
First you set up your GridView with the following properties:
<asp:GridView ID="myGridView" runat="server" 
AutoGenerateColumns="False" AllowPaging="True" AllowSorting="True"
EmptyDataText="No Record Found" OnPageIndexChanging="myGridView_PageIndexChanging"
OnSorting="myGridView_Sorting" PageSize="15" >
AllowPaging and AllowSorting from the name itself allow the following attributes.  OnPageIndexChanging raises the PageIndexChanging event and OnSorting (yup you guessed it right) occurs when the hyperlink to sort a column is clicked, but before the GridView control handles the sort operation.
I also used a drop down list for Paging with a combination of images.  So this is how my PagerTemplate looks like:
<PagerTemplate>
<asp:ImageButton ID="imgPageFirst" runat="server"
ImageUrl="~/Images/Icons/PageFirst.png"
CommandArgument="First" CommandName="Page"
OnCommand="imgPageFirst_Command">
</asp:ImageButton>
<asp:ImageButton ID="imgPagePrevious"
runat="server" ImageUrl="~/Images/Icons/PagePrevious.png"
CommandArgument="Prev" CommandName="Page"
OnCommand="imgPagePrevious_Command">
</asp:ImageButton>
<asp:DropDownList ID="ddCurrentPage" runat="server"
CssClass="Normal" AutoPostBack="True"
OnSelectedIndexChanged="ddCurrentPage_SelectedIndexChanged">
</asp:DropDownList>
<asp:Label ID="lblOf" runat="server" Text="of" CssClass="Normal"></asp:Label>
<asp:Label ID="lblTotalPage" runat="server" CssClass="Normal"></asp:Label>
<asp:ImageButton ID="imgPageNext" runat="server"
ImageUrl="~/Images/Icons/PageNext.png"
CommandArgument="Next" CommandName="Page"
OnCommand="imgPageNext_Command"></asp:ImageButton>
<asp:ImageButton ID="imgPageLast" runat="server"
ImageUrl="~/Images/Icons/PageLast.png"
CommandArgument="Last" CommandName="Page"
OnCommand="imgPageLast_Command"></asp:ImageButton>
</PagerTemplate>
I made the AutoPostBack Property set to true so when a user changes the dropdown values, it will change page.  Now here is the code behind.
public partial class PageControls_SampleTaskList : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindTaskList();
}
}

//Bind your Grid View here
private void BindTaskList()
{
DataSet myDataSet = null; //Set your Dataset here
SetViewState(myDataSet);

myGridView.DataSource = GetViewState();
myGridView.DataBind();
}

private DataSet GetViewState()
{
//Gets the ViewState
return (DataSet)ViewState["myDataSet"];
}

private void SetViewState(DataSet myDataSet)
{
//Sets the ViewState
ViewState["myDataSet"] = myDataSet;
}

protected void myGridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
DataSet myDataSet = GetViewState();
DataTable myDataTable = myDataSet.Tables[0];
myGridView.DataSource = SortDataTable(myDataTable, true);

myGridView.PageIndex = e.NewPageIndex;
myGridView.DataBind();
}

//This is invoked when the grid column is Clicked for Sorting,
//Clicking again will Toggle Descending/Ascending through the Sort Expression
protected void myGridView_Sorting(object sender, GridViewSortEventArgs e)
{
DataSet myDataSet = GetViewState();
DataTable myDataTable = myDataSet.Tables[0];
GridViewSortExpression = e.SortExpression;

//Gets the Pageindex of the GridView.
int iPageIndex = myGridView.PageIndex;
myGridView.DataSource = SortDataTable(myDataTable, false);
myGridView.DataBind();
myGridView.PageIndex = iPageIndex;
}

//Gets or Sets the GridView SortDirection Property
private string GridViewSortDirection
{
get
{
return ViewState["SortDirection"] as string ?? "ASC";
}
set
{
ViewState["SortDirection"] = value;
}
}
//Gets or Sets the GridView SortExpression Property
private string GridViewSortExpression
{
get
{
return ViewState["SortExpression"] as string ?? string.Empty;
}
set
{
ViewState["SortExpression"] = value;
}
}

//Toggles between the Direction of the Sorting
private string GetSortDirection()
{
switch (GridViewSortDirection)
{
case "ASC":
GridViewSortDirection = "DESC";
break;
case "DESC":
GridViewSortDirection = "ASC";
break;
}
return GridViewSortDirection;
}

//Sorts the ResultSet based on the SortExpression and the Selected Column.
protected DataView SortDataTable(DataTable myDataTable, bool isPageIndexChanging)
{
if (myDataTable != null)
{
DataView myDataView = new DataView(myDataTable);
if (GridViewSortExpression != string.Empty)
{
if (isPageIndexChanging)
{
myDataView.Sort = string.Format("{0} {1}",
GridViewSortExpression, GridViewSortDirection);
}
else
{
myDataView.Sort = string.Format("{0} {1}",
GridViewSortExpression, GetSortDirection());
}
}
return myDataView;
}
else
{

return new DataView();
}
}

protected void myGridView_DataBound(object sender, EventArgs e)
{
//Custom Paging
GridViewRow myGridViewRow = myGridView.TopPagerRow;

if (myGridViewRow == null) return;

//Get your Controls from the GridView, in this case
//I use a DropDown Control for Paging
DropDownList ddCurrentPage =
(DropDownList)myGridViewRow.Cells[0].FindControl("ddCurrentPage");
Label lblTotalPage = (Label)myGridViewRow.Cells[0].FindControl("lblTotalPage");

if (ddCurrentPage != null)
{
//Populate Pager
for (int i = 0; i < myGridView.PageCount; i++)
{
int iPageNumber = i + 1;
ListItem myListItem = new ListItem(iPageNumber.ToString());

if (i == myGridView.PageIndex)
myListItem.Selected = true;

ddCurrentPage.Items.Add(myListItem);
}
}

// Populate the Page Count
if (lblTotalPage != null)
lblTotalPage.Text = myGridView.PageCount.ToString();

}

//Change to a different page when the DropDown Page is changed
protected void ddCurrentPage_SelectedIndexChanged(object sender, EventArgs e)
{
{
GridViewRow myGridViewRow = myGridView.TopPagerRow;
DropDownList ddCurrentPage =
(DropDownList)myGridViewRow.Cells[0].FindControl("ddCurrentPage");

myGridView.PageIndex = ddCurrentPage.SelectedIndex;

//Popultate the GridView Control
DataSet myDataSet = GetViewState();
DataTable myDataTable = myDataSet.Tables[0];

myGridView.DataSource = SortDataTable(myDataTable, true);
myGridView.DataBind();
}
}

//Images for |<, <<, >>, and >|
protected void imgPageFirst_Command(object sender, CommandEventArgs e)
{
Paginate(sender, e);
}
protected void imgPagePrevious_Command(object sender, CommandEventArgs e)
{
Paginate(sender, e);
}
protected void imgPageNext_Command(object sender, CommandEventArgs e)
{
Paginate(sender, e);
}
protected void imgPageLast_Command(object sender, CommandEventArgs e)
{
Paginate(sender, e);
}

protected void Paginate(object sender, CommandEventArgs e)
{
// Get the Current Page Selected
int iCurrentIndex = myGridView.PageIndex;

switch (e.CommandArgument.ToString().ToLower())
{
case "first":
myGridView.PageIndex = 0;
break;
case "prev":
if (myGridView.PageIndex != 0)
{
myGridView.PageIndex = iCurrentIndex - 1;
}
break;
case "next":
myGridView.PageIndex = iCurrentIndex + 1;
break;
case "last":
myGridView.PageIndex = myGridView.PageCount;
break;
}

//Populate the GridView Control
DataSet myDataSet = GetViewState();
DataTable myDataTable = myDataSet.Tables[0];

myGridView.DataSource = SortDataTable(myDataTable, true);
myGridView.DataBind();
}
}