2

经典场景:获取用户输入,获取搜索结果并在页面中显示给用户。然后,我需要显示 First、Next、Previous 等按钮,并将用户当前页面保持在 viewstate 中。一切都很好,工作正常。

然后我需要实现可点击的页码,即。1-2-3-4-5-6 等

渲染它们很简单。我在运行时生成一个链接按钮控件,添加带有页码的命令参数并向其添加处理程序,因此要处理单击。然后我将它添加到占位符中,并按预期显示。

但是...

我应该怎么做,所以我的事件总是连接起来并且能够在调用分页链接按钮时触发?

下面是代码的重要部分,一些伪代码使其(希望)更容易理解,我在做什么。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  If Not Page.IsPostBack Then
     Search()
  End If
End Sub

Sub Search
    'Misc databinding stuff, searches and displays results for the page specified in Me.CurrentPage
    RenderPagingControls()
End Sub

Sub RenderPagingControls
   'loop throug pagenumbers, Build a linkbutton control, add it to a placeholder
    AddHandler lbn.Click, AddressOf lbnNumber_Click
    lblPageNumbers.Controls.Add(lbn)
    ...

End Sub

Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim b As LinkButton = CType(sender, LinkButton)
    Me.CurrentPage = CInt(b.CommandArgument)
    Search()
End Sub

Public Property CurrentPage() As Integer
    Get
        Dim o As Object = Me.ViewState("CurrentPage")
        If o Is Nothing Then
            Return 1
        Else
            Return CType(o, Integer)
        End If
    End Get
    Set(ByVal value As Integer)
        Me.ViewState("CurrentPage") = value
    End Set
End Property

Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim b As LinkButton = CType(sender, LinkButton)
    Me.CurrentPage = CInt(b.CommandArgument)
    Search()
End Sub
4

5 回答 5

2

我将建议不要使用 LinkBut​​ton,而是建议使用 Hyperlinks / QueryString 参数。有几个原因:

  1. 如果没有链接按钮的视图状态开销,您的页面将更加高效。
  2. 如果这些是面向公众的页面,那么如果它们可以通过超链接访问(并通过搜索引擎索引),您将获得更好的所有页面索引。
  3. 你会发现它们更容易实现。没有事件管理等。

您可以将 CurrentPage 方法重新定义为(希望这是正确的,我在 C# 方面比 vb.net 更好):

Public Property CurrentPage() As Integer
    Get
        Dim o As Object = Me.Request.QueryString("page")
        If o Is Nothing Then
            Return 1
        Else
            Return CType(o, Integer)
        End If
    End Get
End Property

然后只需为每个页面添加超链接。

<a href='mypage.aspx?page=1'>1</a> - <a href='mypage.aspx?page=2'>2</a>
etc...

备选方案:如果您想使用 LinkBut​​ton,您可能需要考虑在中继器中放置一个 LinkBut​​ton。那么您唯一需要担心的事件就是 OnItemCommand 事件。然后没有动态控件或事件。像这样的东西:

<asp:Repeater ID="rptPages" runat="server" OnItemCommand='doPaging'>
  <ItemTemplate>
    <asp:LinkButton ID="LinkButton1" runat="server" Text='<%# (Container.DataItem).ToString()  %>'
    CommandArgument='<%# (Container.DataItem).ToString() %>' />
  </ItemTemplate>
  <SeparatorTemplate>-</SeparatorTemplate>
</asp:Repeater>

将此控件绑定到连续整数的数组(或列表)(因为有很多页面)。然后在您的 doPaging 函数(我称之为)中,检查 RepeaterCommandEventArgs.CommandArgument 以获取页码。

于 2009-04-06T15:27:26.467 回答
1

谢谢你们的回答,伙计们。我首先尝试了 Austins,但我一定遗漏了一些东西,因为我一直得到相同的链接按钮行为,每秒钟才工作一次……所以我放弃了,并看到了 Keltex 的中继器的替代解决方案!它既简单又出色,我们不必担心任何页面生命周期的废话。

它真的很管用!;)

如果将来有人需要类似的东西,这里是幕后的相关代码:

Sub Search()
    ...
    RenderPagingControls()
End Sub

Sub RenderPagingControls()
    Dim pages As New ArrayList
    For i As Integer = 1 To Me.PageCount
        pages.Add(i)
    Next

    repPageNumbersTop.DataSource = pages
    repPageNumbersTop.DataBind()

    repPageNumbersBottom.DataSource = pages
    repPageNumbersBottom.DataBind()

End Sub

Public Property CurrentPage() As Integer
    Get
        Dim o As Object = Me.ViewState("CurrentPage")
        If o Is Nothing Then
            Return 1
        Else
            Return CType(o, Integer)
        End If
    End Get
    Set(ByVal value As Integer)
        Me.ViewState("CurrentPage") = value
    End Set
End Property

Public Property PageCount() As Integer
    Get
        Dim o As Object = Me.ViewState("PageCount")
        If o Is Nothing Then
            Return 0
        Else
            Return CType(o, Integer)
        End If
    End Get
    Set(ByVal value As Integer)
        Me.ViewState("PageCount") = value
    End Set
End Property


Protected Sub repPageNumbersTop_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles repPageNumbersTop.ItemCommand, repPageNumbersBottom.ItemCommand
    Me.CurrentPage = CType(e.CommandArgument, Integer)
    Search()
End Sub

Private Sub repPageNumbersTop_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repPageNumbersTop.ItemDataBound, repPageNumbersBottom.ItemDataBound
    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
        Dim lbn As LinkButton = CType(e.Item.FindControl("lbnPageNumber"), LinkButton)
        If lbn.CommandArgument = Me.CurrentPage.ToString Then
            lbn.Enabled = False
        End If
    End If
End Sub
于 2009-04-07T09:40:04.047 回答
0

此代码有效(对不起,它在 C# 中):

protected void SearchButton_Click(object sender, EventArgs e)
{
    //clear the collection!
    pnlPageNumber.Controls.Clear();

    //simulate search
    System.Random rnd = new Random();

    //create page buttons
    for (int i = 0; i < rnd.Next(3, 15); i++)
    {
        LinkButton lb = new LinkButton();
        pnlPageNumber.Controls.Add(lb);
        lb.ID = "btn" + i;
        lb.Text = i.ToString();
        lb.CommandArgument = i.ToString();
        lb.Command += new CommandEventHandler(linkbutton_Command);

        //optional literal
        pnlPageNumber.Controls.Add(new LiteralControl(" "));
    }

    ViewState["control#"] = Panel1.Controls.Count;
}

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        //Recreate link buttons
        //This is necessary to ensure proper event binding

        int count = 0;

        if (ViewState["control#"] != null)
            count = (int)ViewState["control#"];

        for (int i = 0; i < count; i++)
        {
            LinkButton lb = new LinkButton();
            pnlPageNumber.Controls.Add(lb);
            lb.ID = "btn" + i; //make sure IDs are the same here and on Search
            lb.Command += new CommandEventHandler(linkbutton_Command);

            //this is not necessary, but if you do, make sure its in both places
            pnlPageNumber.Controls.Add(new LiteralControl(" "));
        }
    }
}

void linkbutton_Command(object sender, CommandEventArgs e)
{
    Response.Write(e.CommandArgument.ToString() + " CLICK<br />");
}
于 2009-04-06T18:04:47.667 回答
0

您可以使用 DataPager 控件——唯一的限制是您必须将它与 ListView 控件一起使用,但是您应该能够相当容易地使用 ListView 控件来表示您的数据,因为它非常灵活。您可以将 ListView 控件的 DataSource 设置为数据结果的结果,无论是 DataSet、Collection、Array 等。

要使用“first”、“last”和页码创建分页控件,请像这样设置 DataPager(其中 ListView1 是 ListView 控件的 ID):

<asp:DataPager ID="DataPager1" runat="server" 
   PagedControlID="ListView1" PageSize="25">
   <Fields>
      <asp:NextPreviousPagerField FirstPageText="first" ShowFirstPageButton="True" 
             ShowNextPageButton="False" ShowPreviousPageButton="False" />
      <asp:NumericPagerField />
      <asp:NextPreviousPagerField LastPageText="last" ShowLastPageButton="True" 
             ShowNextPageButton="False" ShowPreviousPageButton="False" />
   </Fields>
</asp:DataPager>

按照设计,DataPager 使用数据库中的整个结果集,但您可以通过缓存结果并将其用于后续请求来提高性能。

希望这可以帮助。

于 2009-04-07T01:19:41.567 回答
-1

iirc ...在运行时动态添加控件有点棘手。必须在回发期间重建控制树......但在加载视图状态之前(不确定页面生命周期中的时间......但在页面加载之前)。所以...您的问题是,当 asp.net 试图找出您的事件时,尚未创建实际的原始控件。

于 2009-04-06T14:54:07.127 回答