設置 AllowPaging="true" PagerSettings-Mode="NumericFirstLast" 只能產生固定樣式的數字鏈接,無法實現「首頁/尾頁/上一頁/下一頁/頁碼輸入框/Go 按鈕」的完整組合,且樣式難以定制。PagerTemplate 提供完全掌控渲染的能力。
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" PageSize="15"
OnPageIndexChanging="GridView1_PageIndexChanging"
DataKeyNames="Id" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Id" HeaderText="ID" />
<asp:BoundField DataField="Name" HeaderText="名稱" />
</Columns>
<PagerTemplate>
<div class="grid-pager">
<span class="pager-info">
第 <asp:Label ID="lblCurrent" runat="server"
Text='<%# Container.PageIndex + 1 %>' /> 頁 /
共 <asp:Label ID="lblTotal" runat="server"
Text='<%# Container.PageCount %>' /> 頁
</span>
<asp:LinkButton ID="lnkFirst" runat="server" CommandName="Page" CommandArgument="First"
Text="首頁" Visible='<%# Container.PageIndex > 0 %>' CssClass="pager-btn" />
<asp:LinkButton ID="lnkPrev" runat="server" CommandName="Page" CommandArgument="Prev"
Text="上一頁" Visible='<%# Container.PageIndex > 0 %>' CssClass="pager-btn" />
<span class="pager-jump">
轉到第
<asp:TextBox ID="txtPage" runat="server" Width="40px"
Text='<%# Container.PageIndex + 1 %>' CssClass="pager-input" />
頁
<asp:LinkButton ID="lnkGo" runat="server" CommandName="Page" CommandArgument="Go"
Text="GO" CssClass="pager-btn" />
</span>
<asp:LinkButton ID="lnkNext" runat="server" CommandName="Page" CommandArgument="Next"
Text="下一頁" Visible='<%# Container.PageIndex < Container.PageCount - 1 %>' CssClass="pager-btn" />
<asp:LinkButton ID="lnkLast" runat="server" CommandName="Page" CommandArgument="Last"
Text="尾頁" Visible='<%# Container.PageIndex < Container.PageCount - 1 %>' CssClass="pager-btn" />
</div>
</PagerTemplate>
<PagerStyle HorizontalAlign="Center" CssClass="grid-pager-row" />
</asp:GridView>
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
var grid = (GridView)sender;
int newIndex = e.NewPageIndex;
// 處理自定義 CommandArgument:First/Prev/Next/Last/Go
if (e.NewPageIndex == -1) // CommandArgument 非數字時 e.NewPageIndex = -1
{
var args = e.CommandArgument?.ToString();
switch (args)
{
case "First": newIndex = 0; break;
case "Prev": newIndex = Math.Max(0, grid.PageIndex - 1); break;
case "Next": newIndex = Math.Min(grid.PageCount - 1, grid.PageIndex + 1); break;
case "Last": newIndex = grid.PageCount - 1; break;
case "Go":
// 從 PagerTemplate 取得輸入框值
var pagerRow = grid.BottomPagerRow ?? grid.TopPagerRow;
if (pagerRow != null)
{
var txt = pagerRow.FindControl("txtPage") as TextBox;
if (txt != null && int.TryParse(txt.Text, out int input))
newIndex = Math.Clamp(input - 1, 0, grid.PageCount - 1);
}
break;
}
}
// 邊界保護
newIndex = Math.Clamp(newIndex, 0, Math.Max(0, grid.PageCount - 1));
grid.PageIndex = newIndex;
BindGrid(); // 重新綁定數據源
}
private void BindGrid()
{
// 你的數據綁定邏輯
using (var conn = new SqlConnection(connStr))
using (var da = new SqlDataAdapter("SELECT Id, Name FROM Items ORDER BY Id", conn))
{
var dt = new DataTable();
da.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
.grid-pager { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px; flex-wrap: wrap; }
.pager-info { font-size: 14px; color: #666; margin-right: 10px; }
.pager-btn {
display: inline-block; padding: 4px 12px; border: 1px solid #ddd; background: #fff;
color: #333; text-decoration: none; border-radius: 3px; font-size: 13px;
transition: all .2s; cursor: pointer;
}
.pager-btn:hover { background: #007bff; color: #fff; border-color: #007bff; }
.pager-btn:disabled, .pager-btn[style*="display: none"] { display: none !important; }
.pager-jump { display: flex; align-items: center; gap: 4px; font-size: 13px; color: #666; }
.pager-input { width: 50px; height: 26px; padding: 0 6px; border: 1px solid #ddd; border-radius: 3px; text-align: center; }
.grid-pager-row td { padding: 0 !important; border: none !important; }
| 細節 | 說明 |
|---|---|
| Container | PagerTemplate 中的 Container 為 GridViewRow (PagerRow),暴露 PageIndex、PageCount |
| CommandArgument | LinkButton 的 CommandName="Page" 觸發 PageIndexChanging,CommandArgument 傳遞 "First"/"Prev"/"Go" 等 |
| e.NewPageIndex = -1 | 當 CommandArgument 非數字時,框架設置 -1,需自行解析 CommandArgument |
| BottomPagerRow / TopPagerRow | 分頁行對象,用於 FindControl 獲取輸入框,分頁位置由 PagerSettings.Position 決定 |
| Visible 綁定表達式 | '<%# Container.PageIndex > 0 %>' 動態控制首頁/上一頁按鈕顯隱 |
<asp:UpdatePanel ID="upGrid" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ... />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="GridView1" EventName="PageIndexChanging" />
</Triggers>
</asp:UpdatePanel>
配合 UpdatePanel 實現局部刷新,用戶體驗更流暢。
新項目建議:
{ data: [], total: 100 }Element Plus Pagination / Ant Design Pagination / Bootstrap Pagination掌握 PagerTemplate 仍是維護存量 Web Forms 專案的必備技能,上述代碼可直接複製適配至任意 GridView 分頁場景。