13

サーバー側のページングを行うために DataPager を使用しようとしています。これが私のコードです

<asp:DataPager ID="pgrFooBars" PagedControlID="lvFooBars" 
    QueryStringField="page" runat="server" >
<Fields>
    <asp:NumericPagerField />
</Fields>
</asp:DataPager>

コードビハインド

protected void Page_Load(object sender, EventArgs e)
{
    ConfigureBlogPostListView();
}

private void ConfigureBlogPostListView()
{
    int pageNum;
    int.TryParse(Request.Params["page"], out pageNum);
    int pageSize = 20;

    PagedList<IFooBar> FooBars = FooService.GetPagedFooBars(
        new PagingSettings(pageNum, pageSize));

    ListViewPagedDataSource ds = new ListViewPagedDataSource();
    ds.AllowServerPaging = true;
    ds.DataSource = FooBars;
    ds.MaximumRows = pageSize;
    ds.StartRowIndex = pageNum;
    //TotalCount is the total number of records in the entire set, not just those loaded.
    ds.TotalRowCount = FooBars.TotalCount;

    lvFooBars.DataSource = ds;
    lvFooBars.DataBind();

    pgrFooBars.PageSize = pageSize;
    pgrFooBars.SetPageProperties(pageNum, FooBars.TotalCount, true);
}

PagedList は、RobConery の有用な投稿http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/から取得されます。

問題は、DataPager が ListView の Count プロパティを使用して合計レコード数 (この場合は 20) を判断しているように見えることです。どういうわけか、合計レコード数が 20 ではなく、1,500 であることを知る必要があります。DataPager にはプロパティ TotalRowCount がありますが、これは読み取り専用です。

サーバー サイド ページングを使用した DataPager の例を見たことはありませんが、サーバー サイド ページングを実行できると想定していました。

4GuysFromRolla がここで行ったような方法論を使用してカスタム ページング ソリューションを実行できることは承知していますhttp://www.4guysfromrolla.com/articles/031506-1.aspxが、DataPager を使用したソリューションかどうかを最初に知りたいです。カスタム ソリューションを作成する前に可能です。

更新 これを調べれば調べるほど、これは不可能であり、残念ながらデータページャーは小さな Web サイト専用のコントロールであるという結論に達しています。コントロールが正しく構築されていれば、私がやりたいことは非常に単純なはずです。言えるようになりたい

dpFooBars.TotalRowCountComputed = false;
dpFooBars.TotalRowCount = AnyNumberThatISoChoose;

同じことを達成するためのハックを探していましたが、データページャーの TotalRowCount は、バインドされているデータソース内の実際のアイテム数から計算されるようです。Microsoft が ListViewPagedDataSource() クラスと DataPager を同時に作成し、それらを正しく連携させないというのは非常に奇妙に思えますが、これが実際に起こったことのようです。

更新 2 (AHA MOMENT?) ObjectDataSource を使用して SelectCountMethod() をカスタマイズすることにより、.Net 2.0 以降、サーバー側のページングを行うことが可能になったようです。私のニーズに合わせて ObjectDataSource をカスタマイズできるはずです。うーん。私は週末に出かけるので、これが機能するかどうかを確認するのに数日かかります. 真の信者の皆さん、お楽しみに。

4

3 に答える 3

10

リストビュー、データページャー、およびlinqデータソースを利用したSQLサーバーページング - あなたがしたことがまさに必要でした。あなたが言うように、TotalRowCount は読み取り専用です。合計行数を設定するために使用できる SetPageProperties メソッドもありますが、それも私にとってはうまくいきませんでした。

しかし、私はこの方法でそれをだますことができました。アイテム テンプレートが空のダミーの隠しリストビューがあります。ページャーは、元のリストビューではなく、このダミーのリストビューを指しています。次に、ダミーのリストビューを、元のデータ ソースと同じ数の項目を持つダミー コレクションにバインドする必要があります。これにより、ページャーが正しくレンダリングされます。これがマークアップです。

<asp:DataPager ID="pdPagerBottom" runat="server" PagedControlID="lvDummy" PageSize="5" QueryStringField="page">
<Fields>
    <asp:NumericPagerField ButtonType="Link" RenderNonBreakingSpacesBetweenControls="true" NextPageText="Next" PreviousPageText="Previous" ButtonCount="40" />
</Fields>
</asp:DataPager>

<asp:ListView ID="lvDummy" runat="server" Visible="false">
<ItemTemplate></ItemTemplate>
</asp:ListView>

<asp:ListView ID="lvPropertyList" runat="server">...</asp:ListView>

コードビハインド

        var datasourceQuery = context.Properties.OrderBy(x => x.PropertyID).Skip(pdPagerBottom.StartRowIndex).Take(pdPagerBottom.PageSize);

        this.lvPropertyList.DataSource = datasourceQuery;
        this.lvPropertyList.DataBind();

        this.lvDummy.DataSource = new List<int>(Enumerable.Range(0, context.Properties.Count()));
        this.lvDummy.DataBind();

100k レコードでテストしました。御馳走を働きます。

于 2011-09-13T21:33:44.327 に答える
3

サーバー側のページングを DataPager で動作させる唯一の方法はLinqDataSource、マークアップで a を使用し (更新: これは正しくありません。以下を参照)、ListView の DataSourceID を設定することです ( ScottGu のサンプルのように - ステップ 6 )、ListView DataSource プロパティ経由ではありません。ただし、マークアップではなくコード ビハインドを介して LinqDataSource クエリを定義できるように、これをより実行可能にするためのトリックがあることを発見しました (記事では、これはどの DataSource コントロールでも機能すると述べていますが、私はそうは思いませんです)。

これが機能するために必要な IQueryable の結果をおそらく返さない (そして返すべきではない) ある種のサービスを呼び出していることに気付いたので、これはおそらくあなたの状況には何の助けにもなりません。とにかく、興味がある場合はここにあります...

aspx マークアップ:

<asp:ListView ID="lvFooBars" DataSourceID="dsLinq" ....>
   ......
</asp:ListView>

<asp:DataPager ID="pgrFooBars" PagedControlID="lvFooBars" 
    QueryStringField="page" runat="server" >
<Fields>
    <asp:NumericPagerField />
</Fields>
</asp:DataPager>

<asp:LinqDataSource id="dsLinq" runat="server" OnSelecting="dsLinq_Selecting" />

コード ビハインド:

protected void dsLinq_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    //notice this method on FooService requires no paging variables
    e.Result = FooService.GetIQueryableFooBars(); 
}

注意、MSDNQueryStringFieldは属性に関して次のように述べています。

このプロパティの設定は、データのすべてのページを検索エンジンでインデックス化する場合に便利です。これは、コントロールがデータのページごとに異なる URL を生成するために発生します。

更新:実際には、LinqDataSource コントロールの代わりに ObjectDataSource コントロールを使用してこれを機能させることができます -この記事を参照し、サンプルをダウンロードしてください。ObjectDataSource を使用することは、LinqDataSource コントロールを使用するほど単純ではありませんが、使用する魔法の linq 要素が少なく (代わりに、ビジネス/データ レイヤー メソッドにマップする魔法の文字列のヒープを使用します)、データ アクセス メソッドに IEnumerable を公開できます。 IQueryable の代わりに。

それでも、私はUIマークアップに何らかの種類のDataSourceコントロールを埋め込むことを本当に好きではありません(これは必要だと思います)。

ジョンさん、私が気付いたもう 1 つの点は、標準の Asp.Net サーバー コントロール (ViewState に依存する) と、Asp.Net Mvc アプリケーションのヘルパー クラスとして開発された PagedList クラスを結合しようとしているということです。これはうまくいく可能性がありますが、もっと簡単な方法があるかもしれません。

于 2010-07-16T14:20:31.547 に答える
0

ジョン、コードを確認できるように、ここでちょっとした概念実証を行いました。毛羽立ちがないように、これをできるだけ基本的なものにしました。これに欠落している属性が必要な場合はお知らせください。修正します。

目立ったもの:

  1. DataSource オブジェクト (xml、Sql、Access...) を使用していない場合は、ページャーの OnPreRender イベントにデータをバインドする必要があります。これは私が最も問題を抱えていた場所であるため、これはあなたの問題であると確信しています

  2. ListView とページャーで Viewstate を有効にする必要があります (既定では有効になっています)。

コード ビハインド:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            this.BindListData();
        }
    }

    protected void dp_PreRender(object sender, EventArgs e)
    {
        this.BindListData();
    }

    protected void BindListData()
    {
        List<Nums> n = new List<Nums>();
        for (int i = 0; i <= 100; i++)
        {
            n.Add(new Nums { Num1 = i, Num2 = i * 3 });
        }

        this.lvMyGrid.DataSource = n;
        this.lvMyGrid.DataBind();
    }
}

public class Nums
{
    public int Num1 { get; set; }
    public int Num2 { get; set; }
}

ASPX (他の綿毛はすべて除外):

<asp:DataPager OnPreRender="dp_PreRender" runat="server" ID="dpMyPager" QueryStringField="page" PagedControlID="lvMyGrid" PageSize="15">
    <Fields>
        <asp:NumericPagerField />
    </Fields>
</asp:DataPager>

<asp:ListView runat="server" ID="lvMyGrid" DataKeyNames="Num1">
    <LayoutTemplate>
        <asp:Literal runat="server" ID="itemPlaceholder" />
    </LayoutTemplate>
    <ItemTemplate>
        <div style="border: 1px solid red; padding: 3px; margin: 5px; float: left; clear: both;">
        <%# Eval("Num1") %> : <%# Eval("Num2") %>
        </div>
    </ItemTemplate>
</asp:ListView>

お楽しみください。他に必要なものがあれば教えてください。

マイク

于 2010-07-16T04:10:04.710 に答える