2

古典的なシナリオ: ユーザー入力を受け取り、検索結果を取得し、それをページに表示してユーザーに表示します。次に、First、Next、Previous などのボタンを表示する必要があり、ユーザーの現在のページをビューステートに維持します。すべてが良好で、正常に動作します。

次に、クリック可能なページ番号を実装する必要があります。1-2-3-4-5-6など

それらのレンダリングは簡単です。実行時に linkbutton コントロールを生成し、コマンド引数にページ番号を追加し、ハンドラーを追加して、クリックが処理されるようにします。次に、プレースホルダーに追加すると、期待どおりに表示されます。

しかし、もし私がまだ頭を剃っていなかったら、毎回期待通りにイベントを発生させるために髪を引っ張っていたでしょう。

ページングリンクボタンが呼び出されたときにイベントが常に接続され、起動できるようにするにはどうすればよいですか?

以下は、コードの重要な部分です。(できれば) 理解しやすくするためのいくつかの疑似、私が行っていることです。

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メソッドを次のように再定義します(これが正しいことを願っています。vb.netよりもC#の方が優れています)。

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

答えてくれてありがとう、みんな。最初にオースティンを試しましたが、リンクボタンの同じ動作が毎回しか機能しないため、何かが足りないはずです...それで私はそれをあきらめ、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

DataPager コントロールを使用できます。唯一の制限は、ListView コントロールと一緒に使用する必要があることですが、ListView コントロールは非常に柔軟であるため、ListView コントロールを使用してデータを簡単に表すことができるはずです。ListView コントロールの DataSource を、DataSet、Collection、Array などのデータ結果の結果に設定できます。

「最初」、「最後」、およびページ番号を使用してページング コントロールを作成するには、次のように 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 に答える
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 に答える