ASP.NET 4.5 GridView: PostBack of last page ASP.NET 4.5 GridView: PostBack of last page asp.net asp.net

ASP.NET 4.5 GridView: PostBack of last page


As I was not satisfied with my proposed solution (brought too many issues for future development), I have decided to go the "Control development" way to ensure everything is created correctly. It occurs no matter the type of PagerTemplate I am using - I am using one, the postback does not fire from Last page. Hopefully I am not the only one :-)

For those who are experiencing the same issues, I am providing custom control that works OK (of course, does not implement PagerSettings and PagerTemplates, but brings the basic functionality).

public class ExtendedGridView : System.Web.UI.WebControls.GridView{    protected override void InitializePager(System.Web.UI.WebControls.GridViewRow row, int columnSpan, System.Web.UI.WebControls.PagedDataSource pagedDataSource)    {        HtmlGenericControl ul = new HtmlGenericControl("ul");        ul.Attributes.Add("class", "pagination pull-right");        AddPager(ul, commandArgument: "First", text: "<span class='glyphicon glyphicon-fast-backward'></span>");        for (int i = 0; i < PageCount; i++)        {            AddPager(ul, i);        }        AddPager(ul, commandArgument: "Last", text: "<span class='glyphicon glyphicon-fast-forward'></span>");        row.CssClass = "table-footer";        row.Cells.Add(new System.Web.UI.WebControls.TableCell());        row.Cells[0].ColumnSpan = columnSpan;        row.Cells[0].Controls.AddAt(0, ul);                }    protected virtual void navigate_Click(object sender, EventArgs e)    {        string commandArgument = ((System.Web.UI.WebControls.LinkButton)sender).CommandArgument.ToString();        int pageIndex = 0;        if (!int.TryParse(commandArgument, out pageIndex)) {            switch (commandArgument)            {                case "First": pageIndex = 0; break;                case "Last": pageIndex = PageCount - 1; break;                case "Prev": pageIndex = PageIndex - 1; break;                case "Next": pageIndex = PageIndex + 1; break;            }        }        OnPageIndexChanging(new System.Web.UI.WebControls.GridViewPageEventArgs(pageIndex));    }    private void AddPager(System.Web.UI.Control parentControl, int pageIndex = -1, string commandArgument = null, string text = null)    {        HtmlGenericControl li = new HtmlGenericControl("li");        if (pageIndex == PageIndex)            li.Attributes.Add("class", "active");        System.Web.UI.WebControls.LinkButton button = new System.Web.UI.WebControls.LinkButton();        button.CommandName = "Page";        if (text == null)            button.Text = (pageIndex + 1).ToString();        else            button.Text = text;        if (string.IsNullOrWhiteSpace(commandArgument))            button.CommandArgument = string.Format("{0}", pageIndex);        else            button.CommandArgument = commandArgument;        button.Click += navigate_Click;        li.Controls.Add(button);        parentControl.Controls.Add(li);    }}

Just make sure your markup is: - AllowPaging="true" - AllowCustomPaging="false" - PageSize="whatever" - and you still provide VirtualItemCount in code behind

Code behind using SelectMethod could be like this:

protected void Page_Load(object sender, EventArgs e){}public IEnumerable SearchResults_GetData(int startRowIndex, int maximumRows, out int totalRowCount, string sortByExpression){    int pageIndex = (int)(startRowIndex / maximumRows);    return Membership.GetAllUsers(pageIndex, maximumRows, out totalRowCount);}protected void SearchResults_PageIndexChanging(object sender, GridViewPageEventArgs e){    SearchResults.PageIndex = e.NewPageIndex;    SearchResults.DataBind();}

As this is several time I am created serverside controls for .NET using excellent Bootstrap framework, I created a git here https://github.com/Gitzerai/Bootstrap.NET where I put controls that render in a bootstrap proper way.


I found this to happen for me too. On a postback, the last page would "fill-out" the last page with rows from the first page, except the first row after the data. Example: if page size was 10 and I had 25 rows. The last page would show rows 21-25 initially, and then on a postback it would add rows 7-10.

I added the following "hack" to the gridview's RowCreated to prevent drawing these phantom rows. GV is the gridview. DataRowCount is a function which returns the number of rows from the datasource. PageIndex is a property uses a session to hold the current Page Index.

        If e.Row.RowType = DataControlRowType.DataRow Then        Dim RowsLeft As Integer = DataRowCount() - (GV.PageSize * PageIndex)        Dim RowsExpected As Integer        If RowsLeft > GV.PageSize Then            RowsExpected = GV.PageSize        Else            RowsExpected = RowsLeft        End If        If e.Row.RowIndex >= RowsExpected Then            'Last page isn't full, need to force writing nothing out for extra rows            e.Row.SetRenderMethodDelegate(New RenderMethod(AddressOf RenderNothing))        End If    End If

And then I added the following funtion:

Public Sub RenderNothing(writer As HtmlTextWriter, container As Control)End Sub

Since RowCreated happens before ViewState is loaded, the GV's PageIndex wasn't available. So I created a property to hold the PageIndex. So my code now updates the new property and the property saves it to session and updates the GV's property. And this is the property I added

Private Const SS_PagerControl_PageIndex As String = "SSPagerControl_PageIndex"<Bindable(True), CategoryAttribute("Paging"), DefaultValue("0")>Public Property PageIndex As Integer    Get        If Session(SS_PagerControl_PageIndex) Is Nothing Then            Return 0        End If        Return CInt(Session(SS_PagerControl_PageIndex))    End Get    Set(ByVal value As Integer)        Session(SS_PagerControl_PageIndex) = value        GV.PageIndex = value        RebindGrid()    End SetEnd Property