2009-04-06 15 views
2

従来のシナリオ:ユーザーの入力を受け取り、検索結果を取得してページに表示します。 First、Next、Previousなどのボタンを表示する必要があります。ユーザーの現在のページをviewstateで管理しています。すべてが良いです、うまく動作します。検索結果にクリック可能なページ番号を実装する

次に、クリック可能なページ番号を実装する必要があります。 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 
+0

@Kjensenは - 私は、リピータを使用して私の答えで代替を追加しました。あなたはそれをチェックするかもしれません。 – Keltex

答えて

2

私はLinkBut​​tonに対して推奨し、Hyperlinks/QueryStringパラメータを推奨します。いくつかの理由で:

  1. あなたのページは、リンクボタンのviewstateオーバーヘッドなしではるかに効率的になります。
  2. これらが一般公開のページである場合、ハイパーリンク(および検索エンジンを使用して索引付け)でアクセスできる場合は、すべてのページの索引付けが改善されます。
  3. あなたは実装がずっと簡単です。などイベントません管理、

あなたは(うまくいけば、これは正しいですが、私はvb.netよりもC#の時より良いよ)としてあなたcurrentPageにメソッドを再定義しますいいえ:それからちょうどそれぞれのハイパーリンクを追加

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をチェックしてページ番号を取得します。

+0

私はそれについて考えましたが、かなりの数のコントロールがあり、ビューステートを利用していますので、他のコントロールを5-6個追加する必要があります...一方、半日この駄目を働かせるには...私はそれについて考えます。 :) – Kjensen

+0

@Kjensen上記の代替回答を参照してください。私はリピータを使うだけです。次に、あなたはCommandArgumentだけでページを提供します#。 – Keltex

-1

iirc ...実行時に動的にコントロールを追加するのはちょっと難しいです。コントロールツリーは、ポストバック時に再構築する必要がありますが、viewstateがロードされる前に(ページライフサイクルのときは確かではありませんが、ページロードの前に)。だからあなたの問題は、asp.netがあなたのイベントを把握しようとしている頃には、実際に発生したコントロールがまだ作成されていないことです。

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 />"); 
} 
0

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

「最初」、「最後」、およびページ番号を使用してページングコントロールを作成するには、(ListView1のは、あなたのListViewコントロールのIDである)このようなDataPager設定:設計により

<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は、データベースから結果セット全体を使用していますが、結果をキャッシュすることでパフォーマンスを向上させることができますその後のリクエストでこれを使用します。

これが役に立ちます。

1

回答ありがとうございます。私はオースティンを最初に試しましたが、何かが欠けているはずです。なぜなら、私はリンクボタンの同じ振る舞いが2回目ごとにしか働かないからです...だから、私はそれをあきらめ、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 
+0

@Kjensen:私の答えを受け入れてくれてありがとう。また、repPageNumbersTop_ItemDataBoundをLinkBut​​tonのプロパティに置き換えることもできます。Enabled = '<%#(Container.DataItem).ToString <> Me.CurrentPage.ToString%>'(my vb.netはあまり良くありません.. 。) – Keltex

関連する問題