ASP.NET 4.5 GridView: PostBack Last Page

I found a problem with the GridView pager in ASP.NET 4.5 and 4.5.1. Starting with .NET 2-4, I have never encountered such a problem.

By the time, I have a gridview that I populate with data in code like this:

protected int CurrentPage { get { return SearchResults.PageIndex + 1; } } protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack) BindGrid(); } private void BindGrid() { int totalRowCount = 0; SearchResults.DataSource = GetPageData(SearchResults.PageIndex, SearchResults.PageSize, out totalRowCount); SearchResults.VirtualItemCount = totalRowCount; SearchResults.DataBind(); } private IEnumerable GetPageData(int start, int count, out int totalRowCount) { return Membership.GetAllUsers(start, count, out totalRowCount); } protected void SearchResults_PageIndexChanging(object sender, GridViewPageEventArgs e) { SearchResults.PageIndex = e.NewPageIndex; BindGrid(); } 

The problem is that if I get to the last page of the GridView and I try to return to any other page, my IndexChanging page does not work. The problem only occurs if the last page does not have the same number of entries, such as PageSize. The behavior is that my page reloads, the gridview page is filled with empty rows of data to the PageSize value. VirtualItemCount correctly represents the generic ItemCount.

Markup if you find something there:

 <asp:GridView runat="server" CellPadding="0" CellSpacing="0" GridLines="None" CssClass="table table-condensed table-striped table-footer" ID="SearchResults" AllowCustomPaging="true" AllowPaging="true" PageSize="6" OnPageIndexChanging="SearchResults_PageIndexChanging" AutoGenerateColumns="false" UseAccessibleHeader="true"> ... <PagerTemplate> <span class="pull-left"> <strong><%= SearchResults.PageIndex * SearchResults.PageSize + 1 %></strong> - <strong><%= CurrentPage * SearchResults.PageSize %></strong> </span> <span class="pull-left"> Total records: <strong><%= SearchResults.VirtualItemCount %></strong> </span> <ul class="pagination pull-right"> <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="First"><span class="glyphicon glyphicon-backward"></span></asp:LinkButton></li> <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage - 2 %>" Visible="<%# CurrentPage > 2 %>"><%= CurrentPage - 2 %> </asp:LinkButton></li> <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage - 1 %>" Visible="<%# CurrentPage > 1 %>"><%= CurrentPage - 1 %> </asp:LinkButton></li> <li class="active"><a href="#"><%= CurrentPage %></a></li> <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage + 1 %>" Visible="<%# CurrentPage < SearchResults.PageCount %>"><%= CurrentPage + 1 %></asp:LinkButton></li> <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage + 2 %>" Visible="<%# CurrentPage < SearchResults.PageCount - 1 %>"><%= CurrentPage + 2 %></asp:LinkButton></li> <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="Last"><span class="glyphicon glyphicon-forward"></span></asp:LinkButton></li> </ul> </PagerTemplate> </asp:GridView> 

Thank you very much, I have been doing this for several days. Of course, I could use the QueryString approach, but since I will use many tables, I would like to stick with the postback method, if possible ...


EDIT:

The simplest workaround I found was doing a BindGrid on each page of the_Load. For some reason, the PageIndexChanging function just doesn't work on the last page if LastPageSize == PageSize. Then the DataBind is not called to bind the CommandArguments, so I cannot correctly postback.

On the other hand, this is not very clear and can cause problems ... At least double binding = double SQL calls for data on the change page ... Otherwise, I have no idea how to force PageIndexChanging here and it seems like a new problem .NET is for me.

+8
c # gridview paging
source share
2 answers

Since I was not satisfied with the proposed solution (there were too many questions for future development), I decided to follow the "Control" path so that everything would be created correctly. This happens regardless of the type of PagerTemplate that I use - I use one, the postback does not work from the last page. I hope I'm not the only one :-)

For those who are experiencing the same problems, I provide a custom control that works fine (of course, it does not implement PagerSettings and PagerTemplates, but it brings the basic functions).

 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

Code using the SelectMethod method may 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(); } 

Since this is several times, I create server controls for .NET using the excellent Bootstrap framework, I created git here https://github.com/Gitzerai/Bootstrap.NET where I put the controls that appear in the correct boot order.

+2
source share

I found this for me too. Upon postback, the last page will “fill” the last page with lines from the first page, except for the first line after the data. Example: if the page size was 10 and I had 25 lines. On the last page, lines 21-25 will be displayed first, and then lines 7-10 will be added on the back.

I added the following “hack” to the gridview RowCreated to prevent these phantom lines from drawing. GV is the grid. DataRowCount is a function that returns the number of rows from a data source. PageIndex - The property uses a session to store 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 loading ViewState, GV PageIndex is not available. So I created a property to store PageIndex. So my code now updates the new property, and the property saves it to the session and updates the GV property. And this is the property that 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 Set End Property 
0
source share

All Articles