【问题标题】:Dynamically generate page linkbuttons for the PagerTemplate of a GridView为 GridView 的 PagerTemplate 动态生成页面链接按钮
【发布时间】:2014-12-10 17:23:02
【问题描述】:

来自 GridView 控件的 PagerTemplate 的 MSDN 页面(重点是我的):

通常,按钮控件会添加到分页器模板中以执行分页操作。当单击其 CommandName 属性设置为“Page”的按钮控件时,GridView 控件执行分页操作。按钮的 CommandArgument 属性确定要执行的分页操作的类型。

  • “下一页”:导航到下一页。
  • “上一页”:导航到上一页。
  • “第一页”:导航到第一页。
  • “Last”:导航到最后一页。
  • 整数值:导航到指定的页码。

来源:http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.pagertemplate(v=vs.110).aspx

对于下一个/上一个/第一个/最后一个按钮来说,这些东西非常简单,因为它们是静态的。

<PagerTemplate>
    <table>
        <tr>
            <td>
                <asp:Button CommandName="Page" CommandArgument="First" Enabled="<%# Model.PageContext.HasPrevious %>" Text="First" runat="server" />
            </td>
            <td>
                <asp:Button CommandName="Page" CommandArgument="Prev" Enabled="<%# Model.PageContext.HasPrevious %>" Text="Previous" runat="server" />
            </td>
            <td>
                <asp:Button CommandName="Page" CommandArgument="Next" Enabled="<%# Model.PageContext.HasNext %>" Text="Next" runat="server" />
            </td>
            <td>
                <asp:Button CommandName="Page" CommandArgument="Last" Enabled="<%# Model.PageContext.HasNext %>" Text="Last" runat="server" />
            </td>
        </tr>
    </table>
</PagerTemplate>

另一方面,数字按钮的CommandArgument 必须是动态的,并且对于可以导航到的每个页面都是唯一的。我猜我需要for-loop 或转发器控件来在用户的显示屏上获得正确数量的页面链接。

我尝试过的一切似乎都只是有效。我的 for 循环代码甚至无法编译。

<% for (int pageIndex = 0; pageIndex < Model.PageContext.PageCount; pageIndex++) { %>
    <asp:LinkButton CommandName="Page" CommandArgument="<%= pageIndex %>" Text="<%= pageIndex + 1 %>" runat="server"/>
<% } %>

我的替代方法使用Repeatercontrol 并且确实编译,但Repeatercontrol 本身为每个按钮处理ItemCommand,防止“页面”ItemCommand 事件冒泡直到GridView

<asp:Repeater ItemType="System.Int32" SelectMethod="GetPages" runat="server">
    <ItemTemplate>
        <asp:LinkButton CommandName="Page" CommandArgument="<%# Item %>" Text="<%# Item + 1 %>" runat="server" />
    </ItemTemplate>
</asp:Repeater>

每个按钮都会引发正确的事件,但这些事件永远不会到达GridView,因为它们是由Repeater 控件在较低级别处理的。我必须附加一个监听RepeaterCommandEventArgs 的事件处理程序,然后我自己在GridView 上设置新的页面索引。

*深呼吸*

我可以添加数字页面按钮无需自己连接事件吗?

我试图达到的结果,基于上面的代码:

【问题讨论】:

    标签: c# asp.net .net gridview asp.net-4.5


    【解决方案1】:

    我想出了一种使用Repeater 控件完成它的方法。

    首先,使用每个页面索引(从 1 开始)的链接按钮填充转发器,并为 OnItemCommand 事件附加一个事件处理程序。

    <asp:Repeater runat="server" ItemType="System.Int32" SelectMethod="GetPages" OnItemCommand="OnRepeaterCommand">
        <ItemTemplate>
            <asp:LinkButton CommandName="Page" CommandArgument="<%# Item %>" Text="<%# Item %>" runat="server" />
        </ItemTemplate>
    </asp:Repeater>
    

    请特别注意我如何将转发器绑定到由GetPages 返回的int 集合。

    public IEnumerable<int> GetPages()
    {
        return Enumerable.Range(1, this.PageCount);
    }
    

    最后,在事件处理程序中,使用一些反射函数将CommandEventArgs 重新插入到事件管道中。

    protected void OnRepeaterCommand(object source, RepeaterCommandEventArgs e)
    {
        source.GetType()
        .GetMethod("RaiseBubbleEvent", BindingFlags.NonPublic | BindingFlags.Instance)
        .Invoke(source, new[]
        {
            e.CommandSource,
            new CommandEventArgs(e.CommandName, e.CommandArgument)
        });
    }
    

    就是这样。你不必做任何其他事情。 GridView 将处理 ItemCommand 并将页面索引设置为新值。

    【讨论】:

      【解决方案2】:

      我找到了一种更简单的方法,即兼容框架 4.0

      <asp:GridView ID="GridView_History" runat="server">
          <PagerTemplate>
                  <asp:LinkButton ID="lnkPrev" runat="server" CommandName="Page" CommandArgument="Prev">Prev</asp:LinkButton>
                  <asp:Repeater ID="rptPagesHistory" OnItemDataBound="rptPagesHistory_ItemDataBound" runat="server" OnLoad="rptPagesHistory_Load">
                      <ItemTemplate>
                          <asp:LinkButton ID="lnkPageNumber" CommandName="Page" runat="server" OnClick="lnkPageNumberHistory_Click" />
                      </ItemTemplate>
                  </asp:Repeater>
                  <asp:LinkButton ID="lnkNext" runat="server" CommandName="Page" CommandArgument="Next">Next</asp:LinkButton>
          </PagerTemplate>
      </asp:GridView>
      
      
      protected void rptPagesHistory_ItemDataBound(object sender, RepeaterItemEventArgs e)
      {
          LinkButton lnkPageNumber = new LinkButton();
          System.Int32 pageNumber = (System.Int32)e.Item.DataItem;
      
          if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) 
          {
              lnkPageNumber = (LinkButton)e.Item.FindControl("lnkPageNumber");
              lnkPageNumber.Text = pageNumber;
              lnkPageNumber.CommandArgument = pageNumber - 1;
          }
      }
      
      protected void rptPagesHistory_Load(object sender, EventArgs e)
      {
          Repeater rpt = (Repeater)sender;
          rpt.DataSource = Enumerable.Range(1, GridView_History.PageCount);
          rpt.DataBind();
      }
      
      protected void lnkPageNumberHistory_Click(object sender, EventArgs e)
      {
          LinkButton btn = (LinkButton)sender;
          GridView_History.PageIndex = btn.CommandArgument;
          GridView_History.DataBind();
      }
      

      【讨论】:

      • 代码字,但我为类型转换添加了小修复
      • 您好,我尝试修复您的代码,但编辑被拒绝,原因我不清楚。您需要以下修复 lnkPageNumber.Text = pageNumber.ToString(); lnkPageNumber.CommandArgument = (pageNumber - 1).ToString(); GridView_History.PageIndex = Convert.ToInt32(btn.CommandArgument);
      • 不幸的是,这似乎不起作用。除了@ykay 提到的语法错误外,单击寻呼机按钮时,我还会收到“无效的回发或回调参数”。相反,将rptPagesHistory_Load() 的内容移动到GridViewHistory_DataBound 似乎效果更好,如stackoverflow.com/a/4928641/6651
      【解决方案3】:

      这是代码,直接从页面中提取。

      <asp:GridView ID="grdUsage" PageSize="20" Width="100%" runat="server" AllowPaging="True" AllowSorting="False" CellPadding="4" ForeColor="#333333" GridLines="None" Font-Size="14px" Font-Bold="false" OnPageIndexChanging="grdUsage_PageIndexChanging" OnRowDataBound="grdUsage_RowDataBound" AutoGenerateColumns="False">
          <Columns>
              <asp:TemplateField HeaderText="ID" HeaderStyle-HorizontalAlign="Center" ItemStyle-Width="100px" ItemStyle-Font-Size="12px">
                  <ItemTemplate>
                      <asp:Literal ID="lCampaignID" runat="server"></asp:Literal>
                  </ItemTemplate>
              </asp:TemplateField>
              <asp:TemplateField HeaderStyle-HorizontalAlign="Left">
                  <ItemTemplate>
                      <asp:HyperLink ID="lnkCampaign" runat="server" Target="_blank" Font-Size="12px"></asp:HyperLink>
                  </ItemTemplate>
              </asp:TemplateField>
          </Columns>
          <EditRowStyle BackColor="#2461BF" />
          <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
          <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" HorizontalAlign="Left" />
          <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
          <RowStyle BackColor="#EFF3FB" />
          <SelectedRowStyle BackColor="#D1DDF1" ForeColor="#333333" />
          <SortedAscendingCellStyle BackColor="#F5F7FB" />
          <SortedAscendingHeaderStyle BackColor="#6D95E1" />
          <SortedDescendingCellStyle BackColor="#E9EBEF" />
          <SortedDescendingHeaderStyle BackColor="#4870BE" />
          <AlternatingRowStyle BackColor="White" />
          <PagerStyle HorizontalAlign="Center" BackColor="white" />
          <PagerTemplate>
              <ul class="pagination">
                  <li>
                      <asp:LinkButton ID="lnkPrev" runat="server" CommandName="Page" CommandArgument="Prev"><span>&laquo;</span></asp:LinkButton></li>
                  <asp:Repeater ID="rptPagesUsage" OnItemDataBound="rptPagesUsage_ItemDataBound" runat="server" OnLoad="rptPagesUsage_Load">
                      <ItemTemplate>
                          <asp:Literal ID="lListItem" runat="server"><li></asp:Literal><asp:LinkButton ID="lnkPageNumber" CommandName="Page" runat="server"  OnClick="lnkPageNumberUsage_Click" /></li>
                      </ItemTemplate>
                  </asp:Repeater>
                  <li>
                      <asp:LinkButton ID="lnkNext" runat="server" CommandName="Page" CommandArgument="Next"> <span>&raquo;</span></asp:LinkButton></li>
              </ul>
          </PagerTemplate>
      </asp:GridView>
      
      Sub pGrid(sql as string)    '
          grdUsage.DataSource = G_GetDataTable(sql)
          grdUsage.DataBind()
      
          If grdUsage.Rows.Count > 0 Then
              grdUsage.HeaderRow.Cells(1).Text = String.Format("Associated Campaigns for: <i>{0}</i>", txtEMailTitle.Text)
          End If
      End Sub
      
      Protected Sub rptPagesUsage_Load(sender As Object, e As EventArgs)
          Dim rpt As Repeater = DirectCast(sender, Repeater)
          rpt.DataSource = Enumerable.Range(1, grdUsage.PageCount)
          rpt.DataBind()
      End Sub
      
      
      Protected Sub rptPagesUsage_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
          Dim lListItem As New Literal()
          Dim lnkPageNumber As New LinkButton()
      
          Dim pageNumber As System.Int32 = DirectCast(e.Item.DataItem, System.Int32)
      
          If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
              lListItem = DirectCast(e.Item.FindControl("lListItem"), Literal)
              lnkPageNumber = DirectCast(e.Item.FindControl("lnkPageNumber"), LinkButton)
      
              lnkPageNumber.Text = pageNumber
              lnkPageNumber.CommandArgument = pageNumber - 1
      
              If e.Item.ItemIndex = grdUsage.PageIndex Then
                  lListItem.Text = "<li class=""active"">"
              End If
          End If
      End Sub
      
      Protected Sub grdUsage_PageIndexChanging(sender As Object, e As GridViewPageEventArgs)
          hSelectedTab.Value = 5
          If e.NewPageIndex >= 0 Then
              grdUsage.PageIndex = e.NewPageIndex
              pGrid(sql)
          End If
      End Sub
      
      Protected Sub grdUsage_RowDataBound(sender As Object, e As GridViewRowEventArgs)
          Dim drview As DataRowView = DirectCast(e.Row.DataItem, DataRowView)
      
          If e.Row.RowType = DataControlRowType.DataRow Then
              Dim lnkCampaign As HyperLink = DirectCast(e.Row.FindControl("lnkCampaign"), HyperLink)
              Dim lCampaignID As Literal = DirectCast(e.Row.FindControl("lCampaignID"), Literal)
      
              lnkCampaign.Text = drview("CampaignTitle").ToString()
              lCampaignID.Text = drview("EmailCampaignID").ToString()
              lnkCampaign.NavigateUrl = String.Format("/Admin/WF_Admin_Campaign_Email_Detail.aspx?ID={0}", drview("EmailCampaignID").ToString())
          End If
      End Sub
      
      Protected Sub lnkPageNumberUsage_Click(sender As Object, e As EventArgs)
          Dim btn As LinkButton = DirectCast(sender, LinkButton)
          grdUsage.PageIndex = btn.CommandArgument
          pGrid(sql)
      End Sub
      

      我还为正在使用的网格创建了一个扩展。

      Public Module ControlUtilities
          <Extension()>
          Public Sub CustomPager(ByRef grd As GridView)
              Dim cp As New clsCustomPager(grd)
          End Sub
      
      
          Public Class clsCustomPager
      
              Public _grd As GridView
      
              Public Property rpt() As GridView
                  Get
                      Return _grd
                  End Get
                  Set(value As GridView)
                      _grd = value
                  End Set
              End Property
      
      
              Public Sub New(ActiveGridView As GridView)
                  _grd = ActiveGridView
                  Me.CustomPages()
              End Sub
      
              ''' <summary>
              ''' create the objects needed for a bootstrap driven navigation for a gridview
              ''' </summary>
              Sub CustomPages()
                  If Not _grd Is Nothing And Not _grd.BottomPagerRow Is Nothing Then
                      'hook event handler to grid
                      AddHandler _grd.PageIndexChanging, AddressOf Me.Grid_PageIndexChanging
      
                      'declare variables
                      Dim pagerRow As GridViewRow = _grd.BottomPagerRow
                      Dim lnkPrev As LinkButton = New LinkButton()
                      Dim lnkNext As LinkButton = New LinkButton()
      
                      'set up previous link
                      lnkPrev.CommandArgument = "Prev"
                      lnkPrev.CommandName = "Page"
                      lnkPrev.Text = "<span>&laquo;</span>"
      
                      'set up next link
                      lnkNext.CommandArgument = "Next"
                      lnkNext.CommandName = "Page"
                      lnkNext.Text = "<span>&raquo;</span>"
      
                      'create html unordered list
                      pagerRow.Cells(0).Controls.Add(New LiteralControl("<ul class=""pagination"">"))
      
                      'add previous link
                      pagerRow.Cells(0).Controls.Add(New LiteralControl("<li>"))
                      pagerRow.Cells(0).Controls.Add(lnkPrev)
                      pagerRow.Cells(0).Controls.Add(New LiteralControl("</li>"))
      
                      Dim pageNumber As Integer
                      For Each pageNumber In Enumerable.Range(1, _grd.PageCount)
                          'create page link object
                          Dim lnkPage As LinkButton = New LinkButton()
      
                          lnkPage.CommandName = "Page"
                          lnkPage.Text = pageNumber
                          lnkPage.CommandArgument = (pageNumber - 1)
                          AddHandler lnkPage.Click, AddressOf Me.lnkPageNumber_Click 'event handler
      
                          'set css class if selected or not
                          If (pageNumber - 1) = _grd.PageIndex Then
                              pagerRow.Cells(0).Controls.Add(New LiteralControl("<li class=""active"">"))
                          Else
                              pagerRow.Cells(0).Controls.Add(New LiteralControl("<li>"))
                          End If
      
                          'add lnk and close html listitem
                          pagerRow.Cells(0).Controls.Add(lnkPage)
                          pagerRow.Cells(0).Controls.Add(New LiteralControl("</li>"))
                      Next
      
                      'add next link
                      pagerRow.Cells(0).Controls.Add(New LiteralControl("<li>"))
                      pagerRow.Cells(0).Controls.Add(lnkNext)
                      pagerRow.Cells(0).Controls.Add(New LiteralControl("</li>"))
      
                      'close up unordered list
                      pagerRow.Cells(0).Controls.Add(New LiteralControl("</ul>"))
      
                  End If
              End Sub
      
              ''' <summary>
              ''' event handler for previous/next buttons
              ''' </summary>
              Protected Sub Grid_PageIndexChanging(sender As Object, e As GridViewPageEventArgs)
                  If e.NewPageIndex >= 0 Then
                      _grd.PageIndex = e.NewPageIndex
                      _grd.DataBind()
                      Me.CustomPages()
                  End If
              End Sub
      
              ''' <summary>
              ''' event handler for numeric link buttons
              ''' </summary>
              Protected Sub lnkPageNumber_Click(sender As Object, e As EventArgs)
                  Dim btn As LinkButton = DirectCast(sender, LinkButton)
                  _grd.PageIndex = btn.CommandArgument
                  _grd.DataBind()
                  Me.CustomPages()
              End Sub
      
          End Class
      
      End Module
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多