ASP.NET 4.5 网格视图:最后一页的回发
本文关键字:一页 最后 视图 NET 网格 ASP | 更新日期: 2023-09-27 18:31:24
我在 4.5 和 4.5.1 版本中发现了 GridView 寻呼器 ASP.NET 问题。自.NET 2 - 4以来,我从未遇到过这样的问题。
说到这里,我有一个网格视图,我正在用代码后面的数据填充,如下所示:
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();
}
问题是,如果我点击 GridView 的最后一页并尝试返回到任何其他页面,我的 PageIndexChanging 不会触发。仅当最后一页的记录计数与 PageSize 不同时,才会出现问题。行为是我的页面被重新加载,网格视图的页面充满了空数据行,直到 PageSize。VirtualItemCount 正确地表示总 ItemCount。
标记,如果您在那里找到某些内容:
<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>
非常感谢,我已经处理了好几天了。当然,我可以使用 QueryString 方法,但由于我将使用很多表,如果可能的话,我想坚持使用回发方法......
编辑:
我发现最简单的解决方法是在每Page_Load上都做一个 BindGrid。由于某种原因,PageIndexChange不会在最后一页触发,除非LastPageSize == PageSize。然后,为了绑定命令参数,不会调用数据绑定,因此我无法正确回发。
另一方面,它不是很清楚,可能会导致问题......至少双重绑定 = 对 SQL 的双重调用以获取页面更改中的数据...否则,我不知道如何在这里强制PageIndexChange,对我来说似乎是一个新的.NET问题。
由于我对我提出的解决方案不满意(为未来的开发带来了太多问题),我决定采用"控制开发"的方式来确保正确创建所有内容。无论我使用哪种类型的寻呼机模板,都会发生这种情况 - 我正在使用一个,回发不会从最后一页触发。希望我不是唯一一个:-)
对于那些遇到相同问题的人,我提供了工作正常的自定义控件(当然,不实现PagerSettings和PagerTemplates,但带来了基本功能)。
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);
}
}
只需确保您的标记是: - 允许分页="真" - 允许自定义分页="假" - 页面大小="随便" - 并且您仍然在代码隐藏中提供 VirtualItemCount
使用 SelectMethod 隐藏的代码可能是这样的:
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();
}
由于这是我多次使用出色的 Bootstrap 框架为 .NET 创建服务器端控件,因此我在此处创建了一个 git https://github.com/Gitzerai/Bootstrap.NET 在其中放置以引导方式正确呈现的控件。
我发现这也发生在我身上。 在回发时,最后一页将使用第一页中的行"填充"最后一页,但数据后的第一行除外。 示例:如果页面大小为 10,而我有 25 行。 最后一页最初将显示第 21-25 行,然后在回发时添加第 7-10 行。
我将以下"hack"添加到网格视图的 RowCreate 中,以防止绘制这些幻像行。GV 是网格视图。 DataRowCount 是一个从数据源返回行数的函数。 PageIndex 是一个属性,使用会话来保存当前页面索引。
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
然后我添加了以下功能:
Public Sub RenderNothing(writer As HtmlTextWriter, container As Control)
End Sub
由于 RowCreated 发生在加载 ViewState 之前,因此 GV 的 PageIndex 不可用。 所以我创建了一个属性来保存PageIndex。 所以我的代码现在更新新属性,属性将其保存到会话并更新 GV 的属性。 这是我添加的属性
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