2010-07-08 56 views
13

我想使用DataPager做服務器端分頁。這裏是我的代碼如何將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。不知何故,它需要知道有1,500個記錄,而不是20個記錄。 DataPager有一個屬性TotalRowCount,但是這是隻讀的。

我從來沒有見過使用服務器端分頁的DataPager示例,但假定它可以執行服務器端分頁,否則QueryStringField屬性有什麼好處?

我知道你可以使用4GuysFromRolla在這裏做的http://www.4guysfromrolla.com/articles/031506-1.aspx這樣的方法來做一個自定義分頁解決方案,但是我首先想知道在創建自定義解決方案之前是否可以使用DataPager解決方案。

UPDATE 我越是看這個,越覺得我來的結論是,這是不可能的,不幸的是,DataPager的是控制意味着只有小網站。如果控件構建正確,我想要做的事情應該非常簡單。我想可以說

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

我一直在尋找一些黑客來完成同樣的事情,但現在看來,DataPager的的TotalRowCount是從它綁定到數據源項目的實際數量計算。對我來說,看起來很奇怪,微軟會同時創建一個ListViewPagedDataSource()類和一個DataPager,並且它們不會一起正確工作,但這似乎是發生了什麼。

更新2(AHA時刻?) 看來,它已通過使用一個ObjectDataSource和定製SelectCountMethod是不可能做服務器端分頁因爲NET 2.0()。我相信應該可以自定義ObjectDataSource來滿足我的需求。嗯。我要在週末外出,所以我需要幾天的時間才能看到這是否有效。敬請關注,真正的信徒。

+0

你的應用程序是webform應用程序或Asp.Net MVC? – Sharique 2010-07-14 12:14:52

回答

3

這似乎讓服務器端分頁與DataPager的工作的唯一方法是使用LinqDataSource在您的標記(更新:這是不正確的,見下文),並設置ListView的DataSourceID(如ScottGu's sample - step 6),而不是通過ListView DataSource屬性。但是我確實發現有一個trick可以使這更加可行,因此您可以通過代碼隱藏而不是標記來定義您的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 。

更新: INFACT你能得到這個使用ObjectDataSource控件,而不是LinqDataSource控件的工作 - 看this article and download the sample。雖然使用ObjectDataSource並不像使用LinqDataSource控件那麼簡單,但它使用的是更少的magic linq東西(而不是使用映射到業務/數據層方法的魔術字符串),並允許將IEnumerable暴露給您的數據訪問方法而不是IQueryable。儘管如此,我從來沒有真正喜歡在我的UI標記中嵌入任何類型的DataSource控件(我相信這是必要的),所以我可能會避開DataPager控件,除了小應用程序之外,正如您所建議的你的第一次更新。

約翰,我注意到的另一件事是,你試圖與標準的Asp.Net服務器控件(依賴於ViewState)結合的PagedList類,它是作爲Asp.Net Mvc應用程序的輔助類而開發的。雖然這可能有效,但可能有更簡單的路線。

+0

感謝您的提示。微軟將他們的數據訪問層與應用層緊密結合的魅力在繼續。 – John 2010-07-16 15:34:16

+1

謝謝,我來看看。這似乎是我所需要的。我真的不認爲PagedList是一個MVC的東西,更像是一個Rob Conery的東西。在我找到PagedList之前,我之前的人一直在使用List GetFoobars(字符串id,out TotalRowCount)之類的方法。對我而言,PagedList只是一種很好的O-O做事的方式,而不是使用一種外觀,這讓我感覺不太舒服。 – John 2010-07-18 01:34:48

+0

我認爲更簡單的路線就是使用MVC開始,但團隊尚未準備好轉換此網站(我們正在開始使用其他地方)。我個人的感覺是,除了最簡單的網站之外,MVC比網頁形式要容易得多。 – John 2010-07-18 01:41:54

0

John,我在這裏做了一點概念驗證,以便您可以看到代碼。我儘可能地做到這一點,所以沒有絨毛。請讓我知道,如果有這個屬性,你需要缺少,我會修改。

事情站出來:

  1. 的數據需要,當你不使用數據源對象(XML,SQL,訪問...)在尋呼機的OnPreRender事件被綁定。我是漂亮的確定這是你的問題,因爲這是我遇到的最大麻煩。

  2. 視圖狀態必須在ListView和尋呼機(這是默認情況下)啓用

代碼隱藏:

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> 

享受,讓我知道如果有什麼你需要的東西。

邁克

+0

不幸的是,這不是我所需要的。我需要做服務器端分頁,也就是說,我在數據庫中有1000條記錄,但爲了節省帶寬,我只會從數據庫中下載15條記錄。假設我在數據庫中有10,000條記錄。我不想從數據庫中獲取所有10,000條記錄,以便數據設置器可以正確計數。 – John 2010-07-16 14:37:34

+0

好吧,這很有道理,爲什麼這更復雜。你可能要做的就是創建一個像ICollection FooBarCollection這樣的自定義集合,並重寫Count方法,以便它返回你的整個計數。我不確定這是否會起作用,但可能您必須這樣做才能欺騙DataPager,使其認爲這裏存在更多數據。 – Jerzakie 2010-07-16 16:20:44

10

確實需要你做的 - SQL服務器分頁利用listview,datapager和linq數據源。正如你所說的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記錄進行了測試。作品一種享受。

+0

有趣的解決方法。我現在通過去MVC路線避免了這個問題:-) – John 2011-10-31 01:11:18

+0

這個答案很棒...快速簡單,並且可以獲得數據尋呼機的所有好處。謝謝 – clamchoda 2017-11-03 00:37:31

相關問題