如何在服务器端分页中使用DataPager?

Joh*_*ohn 13 asp.net server-side datapager

我正在尝试使用DataPager进行服务器端分页.这是我的代码

<asp:DataPager ID="pgrFooBars" PagedControlID="lvFooBars" 
    QueryStringField="page" runat="server" >
<Fields>
    <asp:NumericPagerField />
</Fields>
</asp:DataPager>
Run Code Online (Sandbox Code Playgroud)

代码背后

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);
}
Run Code Online (Sandbox Code Playgroud)

PagedList来自RobConery的有用帖子http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/.

问题是DataPager似乎使用ListView的Count属性来确定记录的总数,在这种情况下是20.不知何故,它需要知道有1,500条记录而不是20条记录.DataPager具有属性TotalRowCount,但这是只读的.

我从未见过使用服务器端分页的DataPager示例,但假设它可以执行服务器端分页,否则QueryStringField属性有什么用呢?

我知道你可以使用类似4GuysFromRolla这样的方法做自定义分页解决方案http://www.4guysfromrolla.com/articles/031506-1.aspx,但我首先想知道是否有一个DataPager的解决方案在创建自定义解决方案之前是可行的

更新 我看到的越多,我就越能得出结论,这是不可能的,不幸的是,数据采集器只是针对小型网站的控件.如果正确构建控件,我想要做的事情应该非常简单.我希望能够说出来

dpFooBars.TotalRowCountComputed = false;
dpFooBars.TotalRowCount = AnyNumberThatISoChoose;
Run Code Online (Sandbox Code Playgroud)

我一直在寻找一些黑客来完成同样的事情,但似乎数据删除器的TotalRowCount是根据它绑定的数据源中的实际项目数来计算的.对我来说,微软会同时创建一个ListViewPagedDataSource()类和一个DataPager而不是让它们一起正常工作似乎很奇怪,但这似乎已经发生了什么.

更新2(AHA MOMENT?) 似乎可以通过使用ObjectDataSource和自定义SelectCountMethod()从.Net 2.0开始进行服务器端分页.我相信应该可以自定义ObjectDataSource以满足我的需求.嗯.我要去周末,所以我要花几天时间看看这是否有效.敬请关注,真正的信徒.

Dav*_*vid 10

完全需要你做的 - 使用listview,datapager和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>
Run Code Online (Sandbox Code Playgroud)

和代码背后

        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();
Run Code Online (Sandbox Code Playgroud)

用100k记录测试它.工作一种享受.


Ber*_*rmo 3

LinqDataSource似乎让服务器端分页与 DataPager 一起使用的唯一方法是在标记中使用 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" />
Run Code Online (Sandbox Code Playgroud)

代码隐藏:

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

请注意,MSDN关于该QueryStringField属性的说明:

如果您希望搜索引擎对所有数据页建立索引,则设置此属性非常有用。发生这种情况是因为控件为每个数据页生成不同的 URL。

更新:事实上,您可以使用 ObjectDataSource 控件而不是 LinqDataSource 控件来使其工作 - 请参阅本文并下载示例。虽然使用 ObjectDataSource 并不像使用 LinqDataSource 控件那么简单,但它使用的魔法 linq 内容较少(相反,它使用映射到业务/数据层方法的魔法字符串堆),并且允许为数据访问方法公开 IEnumerable而不是 IQueryable。

尽管如此,我从来没有真正喜欢在我的 UI 标记中嵌入任何类型的 DataSource 控件(我相信这是必要的),因此我可能会避开 DataPager 控件,除了您在第一次更新中建议的小型应用程序之外。

John,我注意到的另一件事是,您正在尝试将标准 Asp.Net 服务器控件(依赖于 ViewState)与 PagedList 类结合起来,该类是作为 Asp.Net Mvc 应用程序的帮助程序类开发的。虽然这可能有效,但可能还有更简单的路线可供选择。