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.