如何将 DataPager 与服务器端分页结合使用?
我正在尝试使用 DataPager 进行服务器端分页。这是我的代码
<asp:DataPager ID="pgrFooBars" PagedControlID="lvFooBars"
QueryStringField="page" runat="server" >
<Fields>
<asp:NumericPagerField />
</Fields>
</asp:DataPager>
PagedList背后的代码
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);
}
来自 RobConery 的有用帖子 http:// blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/。
问题是 DataPager 似乎使用 ListView 的 Count 属性来确定记录总数,在本例中为 20 条。不知何故,它需要知道总共有 1,500 条记录,而不是 20 条记录。 DataPager 有一个属性 TotalRowCount,但它是只读的。
我从未见过带有服务器端分页的 DataPager 示例,但假设它可以进行服务器端分页,否则 QueryStringField 属性有什么用?
我知道您可以使用 4GuysFromRolla 此处所做的方法来执行自定义分页解决方案 https://web.archive.org/web/20211020140032/https://www.4guysfromrolla.com/articles/031506-1.aspx,但我'在创建自定义解决方案之前,我首先想知道使用 DataPager 的解决方案是否可行。
更新 我对此了解得越多,就越得出这样的结论:这是不可能的,不幸的是,数据页程序是仅适用于小型网站的控件。如果控件构建正确的话,我想做的事情应该非常简单。我想说
dpFooBars.TotalRowCountComputed = false;
dpFooBars.TotalRowCount = AnyNumberThatISoChoose;
我一直在寻找一些技巧来完成同样的事情,但似乎数据分页器的 TotalRowCount 是根据它绑定到的数据源中的实际项目数计算的。对我来说,微软会同时创建一个 ListViewPagedDataSource() 类和一个 DataPager 类,而不让它们一起正常工作,这似乎很奇怪,但这似乎已经发生了。
更新 2(啊哈时刻?) 从 .Net 2.0 开始,似乎可以通过使用 ObjectDataSource 并自定义 SelectCountMethod() 来进行服务器端分页。我相信应该可以自定义 ObjectDataSource 来满足我的需求。嗯。我周末要出去,所以我需要几天时间看看这是否有效。请继续关注,真正的信徒。
I'm trying to use a DataPager to do Server Side paging. Here is my code
<asp:DataPager ID="pgrFooBars" PagedControlID="lvFooBars"
QueryStringField="page" runat="server" >
<Fields>
<asp:NumericPagerField />
</Fields>
</asp:DataPager>
Code Behind
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 comes from RobConery's useful post http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/.
The problem is that the DataPager appears to be using the Count property of the ListView to determine the total number of records, which in this case is 20. Somehow, it needs to know that there are 1,500, not 20 total records. The DataPager has a property TotalRowCount, but this is read-only.
I have never seen a DataPager example with Server Side paging, but assumed that it could do Server Side Paging, otherwise what good is the QueryStringField attribute?
I am aware that you can do a custom paging solution using methodology like the 4GuysFromRolla did here https://web.archive.org/web/20211020140032/https://www.4guysfromrolla.com/articles/031506-1.aspx, but I'd first like to know if a solution with the DataPager is possible before creating a custom solution.
UPDATE
The more I look at this, the more that I'm coming to the conclusion that this is not possible and that, unfortunately, the datapager is a control meant for small web sites only. What I want to do should really be quite simple if the control were built correctly. I want to be able to say
dpFooBars.TotalRowCountComputed = false;
dpFooBars.TotalRowCount = AnyNumberThatISoChoose;
I've been looking for some hack to accomplish the same thing, but it appears that the datapager's TotalRowCount is computed from the actual number of items in the datasource that it's bound to. It seems very odd to me that Microsoft would create a ListViewPagedDataSource() class and a DataPager at the same time and not have them work correctly together, but this appears to have been what has happened.
UPDATE 2 (AHA MOMENT?)
It seems that it has been possible to do server side paging since .Net 2.0 by using an ObjectDataSource and customizing the SelectCountMethod(). I believe it should be possible to customize ObjectDataSource to suit my needs. Hmmm. I'm going away for the weekend, so it'll be a couple of days for me to see if this works. Stay tuned, true believers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正是需要您所做的 - SQL Server 分页利用 listview、datapager 和 linq 数据源。正如您所说,TotalRowCount 是只读的。还有 SetPageProperties 方法可用于设置总行数,但这对我来说也不起作用。
然而我设法用这种方法欺骗了它。我有一个带有空项目模板的虚拟隐藏列表视图。寻呼机将指向这个虚拟列表视图而不是原始列表视图。然后我们需要将虚拟列表视图绑定到一个虚拟集合,该集合的项目数与原始数据源中的项目数相同。这将确保正确呈现寻呼机。这是标记。
和后面的代码
用 100k 记录对其进行了测试。工作是一种享受。
Exactly needed what you did - SQL server paging utilizing listview, datapager and linq data source. As you say TotalRowCount is readonly. There is also SetPageProperties method that can be used to set the total row count but that also didn't work for me.
However I managed to trick it this way. I have a dummy hidden listview with empty item template. The pager will be pointing at this dummy listview rather than the original listview. Then we need to bind the dummy listview to a dummy collection with the same number of items as in the original data source. This will ensure rendering the pager correctly. Here is the markup.
and code behind
Tested it with 100k records. Works a treat.
似乎让服务器端分页与 DataPager 一起使用的唯一方法是在标记中使用
LinqDataSource
(更新:这不是真的,请参见下文),并设置 ListView 的 DataSourceID (如 ScottGu 的示例 - 步骤 6),而不是通过 ListView DataSource 属性。然而我确实发现有一个 技巧 使此操作更加可行,以便您可以通过代码隐藏而不是在标记中定义 LinqDataSource 查询(请注意,文章说这适用于任何 DataSource 控件,但我认为情况并非如此)。这可能对您的情况没有任何帮助,因为我注意到您调用的某种服务可能不会(也不应该)返回 IQueryable 结果,这是工作所必需的。无论如何,如果您感兴趣的话,它就在这里......
aspx 标记:
代码隐藏:
注意,MSDN 有关
QueryStringField
属性的说明:更新:事实上,您可以使用 ObjectDataSource 控件而不是 LinqDataSource 控件来使其工作 - 请参阅 本文并下载示例。虽然使用 ObjectDataSource 并不像使用 LinqDataSource 控件那么简单,但它使用的魔法 linq 内容较少(相反,它使用映射到业务/数据层方法的魔法字符串堆),并且允许为数据访问方法公开 IEnumerable而不是 IQueryable。
尽管如此,我从来没有真正喜欢在我的 UI 标记中嵌入任何类型的 DataSource 控件(我认为这是必要的),因此我可能会避开 DataPager 控件,除了您在第一次更新中建议的小型应用程序之外。
John,我注意到的另一件事是,您正在尝试将标准 Asp.Net 服务器控件(依赖于 ViewState)与 PagedList 类结合起来,该类是作为 Asp.Net Mvc 应用程序的帮助程序类开发的。虽然这可能有效,但可能还有更简单的路线可供选择。
It seems the only way to get server-side paging to work with the DataPager is to use a
LinqDataSource
in your markup (update: this is not true, see below), and set the DataSourceID of your ListView (as in ScottGu's sample - step 6), not via the ListView DataSource property. However I did discover that there is a trick to make this more workable so you can define your LinqDataSource query via code-behind rather than in the markup (note, the article says this will work with any DataSource control but I don't think it is the case).This will probably not be any help for your situation as I noticed that your calling some sort of service that probably won't (and shouldn't) be returning an IQueryable result which is necessary for this to work. Here it is anyway in-case you're interested ...
aspx markup:
code-behind:
Note, MSDN states in regards to the
QueryStringField
attribute:Update: infact you can get this to working using an ObjectDataSource control instead of the LinqDataSource control - see this article and download the sample. While using an ObjectDataSource isn't nearly as simple as using a LinqDataSource control, it's uses less magic linq stuff (instead it uses heaps of magic strings that map to business/data layer methods) and allows the exposure of IEnumerable for your data access method instead of IQueryable.
Still, I have never really a fan of embedding any sort of DataSource control in my UI markup (I believe this is necessary), so I would probably steer clear of the DataPager control except for small applications as you have suggested in your first update.
John, one other thing I noticed was that you are trying to marry standard Asp.Net server controls (that rely on ViewState) with the PagedList class which was developed as a helper class for Asp.Net Mvc applications. While this can potentially work, there may be simpler routes to take.
约翰,我在这里做了一些概念验证,以便您可以看到代码。我把它做得尽可能基本,这样就不会有任何废话。如果您需要的某些属性缺失,请告诉我,我将进行修改。
突出的事情:
当您不使用数据源对象(xml、Sql、Access...)时,需要将数据绑定到寻呼机的 OnPreRender 事件上。我非常确定这是您的问题,因为这是我遇到最多麻烦的地方。
必须在 ListView 和分页器上启用 Viewstate(默认情况下)
代码隐藏:
ASPX(忽略所有其他fluff):
享受吧,如果您还需要其他东西,请告诉我。
麦克风
John, I did a little proof of concept here so that you can see the code. I made this as basic as possible so there's no fluff. Please let me know if there is some attribute to this that you need that is missing and I will revise.
Things that stood out:
The data needs to be bound on the OnPreRender event of the pager when you're not using a DataSource object (xml,Sql,Access...). I am pretty sure this is your issue because this is where I had the most trouble.
Viewstate must be enabled on the ListView and the pager (it is by default)
Code-Behind:
ASPX (left out all the other fluff):
Enjoy, let me know if there is something else in this that you need.
mike