动态生成GridView的PagerTemplate的页面链接按钮

时间:2014-10-15 15:04:07

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

PagerTemplate控件的GridView的MSDN页面中(强调我的):

  

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

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

来源: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循环或转发器控件来在用户的显示器上获得正确数量的页面链接。

我尝试的任何内容似乎只是工作。我的for循环代码甚至都没有编译。

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

我的替代方法使用Repeater控件并且执行编译,但Repeater控件本身会处理每个按钮的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自己设置新的页面索引。

*深呼吸*

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

我想要实现的结果,基于上面的代码:

linkbuttons

3 个答案:

答案 0 :(得分:2)

我想出了一种使用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>

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

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并将页面索引设置为新值。

答案 1 :(得分: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();
}

答案 2 :(得分:0)

这是代码,从页面上抬起。

<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