Effective Paging and Sorting using GridView – Part II
In my previous article, I have shown how to use effective paging and sorting using gridview and ObjectDataSource, where you have millions of records and display records in grid which will affect performance problem. Here, I am doing same but without using ObjectDataSource. Here, I will be binding grid manually using dataset.
Download Source Code here.
I will be passing three parameters to store procedure to get records. StartRowIndex, MaximumRows and SortExpression. StartRowIndex will be grid current page index, MaximumRows will be grid page size, And SortExpression will be use for sorting grid. I created GridBind() method which will bind data to grid, which will call method GetCustomer() of customer class. In this, I will be passing above mention three parameters. Code snippets looks like below one.
private void GridBind(int StartRowIndex, int MaximumRows, String SortExpression) { gvCustomer.DataSource = cust.GetCustomer(StartRowIndex, MaximumRows, SortExpression); gvCustomer.DataBind(); } |
I am using PagerTemplate to display pagination in grid. Where, I will display as First, Prev,Next and Last for navigation purpose.
<PagerTemplate> <table> <tr> <td> <asp:LinkButton ID="lnkFirst" Text="<< First" Visible="false" OnCommand="gvPaging_Click" CommandArgument="First" ToolTip="First Page" runat="server" /> </td> <td> <asp:LinkButton ID="lnkPrevious" Text="< Prev" Visible="false" OnCommand="gvPaging_Click" CommandArgument="Prev" ToolTip="Prev Page" runat="server" /> </td> <td> <asp:LinkButton OnCommand="gvPaging_Click" Visible="false" ID="lnkNext" Text="Next >" CommandArgument="Next" ToolTip="Next Page" runat="server" /> </td> <td> <asp:LinkButton ID="lnkLast" Text="Last >>" Visible="false" OnCommand="gvPaging_Click" CommandArgument="Last" ToolTip="Last Page" runat="server" /> </td> </tr> </table> </PagerTemplate> |
Just, one thing to note about PagerTemplate is that when you have record less or equal to grid page size. It won’t display PagerTemplate . For this purpose, we have to grid pre-Render method. Inside that we have to make BottomPagerRow visible true.
protected void gvCustomer_PreRender(object sender, EventArgs e) { gvCustomer.BottomPagerRow.Visible = true; } |
For navigation purpose, I am using OnCommand event for all 4 links button (i.e. :- First, Prev, Next and Last). A common method created gvPaging_click where all link button click event has been called. CommandArgument property has been used for determining which link button has been clicked.
protected void gvPaging_Click(object sender, CommandEventArgs e) { string sortExpression=ViewState["sortExpression"].ToString() + " " + ViewState["Sort"].ToString();
if (e.CommandArgument.Equals("First")) { pageIndex = 0; ViewState["pageIndex"] = 0; GridBind(pageIndex * gvCustomer.PageSize, gvCustomer.PageSize, sortExpression); } else if (e.CommandArgument.Equals("Next")) { ViewState["pageIndex"] = int.Parse(ViewState["pageIndex"].ToString()) + 1; pageIndex = int.Parse(ViewState["pageIndex"].ToString()); GridBind(pageIndex * gvCustomer.PageSize, gvCustomer.PageSize, sortExpression); } else if (e.CommandArgument.Equals("Prev")) { ViewState["pageIndex"] = int.Parse(ViewState["pageIndex"].ToString()) - 1; pageIndex = int.Parse(ViewState["pageIndex"].ToString()); previous = true; GridBind(pageIndex * gvCustomer.PageSize, gvCustomer.PageSize, sortExpression); } else { decimal countRow = cust.GetCustomerCount(); int pageSize = int.Parse(Math.Ceiling((countRow / gvCustomer.PageSize)).ToString());
ViewState["pageIndex"] = pageSize -1; pageIndex = pageSize -1; GridBind(pageIndex * gvCustomer.PageSize, gvCustomer.PageSize, sortExpression); } } |
ViewState["pageIndex"] will add its value depend on which link button has been clicked. Eg for First value will be 0, Prev and Next value will be –1 and +1 respectively for current page index. When last row has been clicked at that time, I am calling GetCustomerCount() method, which will count total number of records in Database. To, get the actual page count, its has been divided with grid page size.
To, make navigation link visible true and false, depends on which has been clicked, Grid Databound event has been used.
protected void gvCustomer_DataBound(object sender, EventArgs e) {
decimal countRow = cust.GetCustomerCount(); int pageSize = int.Parse(Math.Ceiling((countRow / gvCustomer.PageSize)).ToString());
LinkButton lnkFirst = (LinkButton)gvCustomer.BottomPagerRow.FindControl("lnkFirst"); LinkButton lnkPrevious = (LinkButton)gvCustomer.BottomPagerRow.FindControl("lnkPrevious"); LinkButton lnkNext = (LinkButton)gvCustomer.BottomPagerRow.FindControl("lnkNext"); LinkButton lnkLast = (LinkButton)gvCustomer.BottomPagerRow.FindControl("lnkLast");
if (pageIndex == 0) { lnkNext.Visible = true; lnkLast.Visible = true; lnkFirst.Visible = false; lnkPrevious.Visible = false; } else if (pageIndex == pageSize) { lnkFirst.Visible = true; lnkPrevious.Visible = true; lnkNext.Visible = false; lnkLast.Visible = false; } else if (pageIndex >= 1 && pageIndex < (pageSize -1)) { lnkFirst.Visible = true; lnkPrevious.Visible = true; lnkNext.Visible = true; lnkLast.Visible = true; } else { if (previous) { lnkFirst.Visible = true; lnkPrevious.Visible = true; lnkNext.Visible = true; lnkLast.Visible = true; } else { lnkFirst.Visible = true; lnkPrevious.Visible = true; lnkNext.Visible = false; lnkLast.Visible = false; } } } |
Code is simple to understand, Just using find control, getting link button id. making link button visible true/false according which link button has been clicked. Just one problem I face in this is, when user click from Last navigation to previous navigation at that time it still shows only first and previous navigation link button but not all links. One work around I use is having boolean variable previous and assign its value whenever previous link button has been clicked.
For sorting, I am using grid view sorting event. SortExpression is used for which column has been sorted.
protected void gvCustomer_Sorting(object sender, GridViewSortEventArgs e) { ViewState["sortExpression"] = e.SortExpression; string sortExpression = ViewState["sortExpression"].ToString() + " " + ViewState["Sort"].ToString(); if (ViewState["Sort"] as string == "ASC") { ViewState["Sort"] = "DESC"; } else { ViewState["Sort"] = "ASC"; } GridBind(int.Parse(ViewState["pageIndex"].ToString()), gvCustomer.PageSize, sortExpression); } |
Store Procedure is same as which I had used in previous article, you can check out here, how i used it. And, also I will be giving download link for this source code and sp script.
Screen Shot :-
I hope you will like this article about effective pagination and sorting without using ObjectDataSource.