2010-07-08 16 views
13

DataPager를 사용하여 Server Side 페이징을 시도하고 있습니다. 여기에 내 코드서버 측 페이징과 함께 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/에서 오는 뒤에

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

코드입니다.

문제는 DataPager가 총 레코드 수를 결정하기 위해 ListView의 Count 속성을 사용하는 것처럼 보입니다.이 경우 20입니다. 어쨌든, 총 레코드 수는 1,500 개가 아니라 총 레코드 수를 알아야합니다. . DataPager에는 TotalRowCount 속성이 있지만 읽기 전용입니다.

서버 측 페이징으로 DataPager 예제를 본 적이 없지만 서버 측 페이징을 수행 할 수 있다고 가정합니다. 그렇지 않으면 QueryStringField 특성이 무엇입니까?

여기서 4GuysFromRolla와 같은 방법론을 사용하여 사용자 지정 페이징 솔루션을 수행 할 수 있다는 것을 알고 있습니다 만, http://www.4guysfromrolla.com/articles/031506-1.aspx과 같은 방법이지만 사용자 지정 솔루션을 만들기 전에 DataPager를 사용하여 솔루션을 사용할 수 있는지 먼저 알고 싶습니다.

UPDATE 는 더 나는이 불가능하며 즉, 불행하게도있는 DataPager는 컨트롤이 작은 웹 사이트만을위한 의미라고 나는 결론에 간다 것을 더, 이것 좀 봐. 컨트롤이 올바르게 구축 되었다면 내가하고 싶은 일은 실제로 아주 간단해야합니다. 나는 같은 일을 수행하는 몇 가지 해킹을 찾고 있었어요

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

말할 수 있도록하려면,하지만있는 DataPager의 TotalRowCount가가에 바인딩 된 데이터 소스의 항목의 실제 수에서 계산 된 것 같습니다 . Microsoft가 ListViewPagedDataSource() 클래스와 DataPager를 동시에 만들고 제대로 함께 작동시키지 못하는 것은 매우 이상한 것처럼 보입니다. 그러나이 문제가 발생한 것으로 보입니다.

업데이트 2 (AHA 순간은?) 그것은는 SelectCountMethod을 ObjectDataSource를를 사용하여 사용자 정의하여 닷넷 2.0부터 서버 측 페이징을 할 수 있었다 것 같다(). 내 요구에 맞게 ObjectDataSource를 사용자 정의 할 수 있어야한다고 생각합니다. 흠. 나는 주말 동안 떠날 것이기 때문에, 이것이 작동하는지 알기까지 며칠이 걸릴 것이다. 진정한 신자들을 지켜보십시오.

+0

앱이 webform 앱 또는 Asp.Net MVC입니까? – Sharique

답변

3

그것은있는 DataPager 함께 작동하는 서버 측 페이징을 얻을 수있는 유일한 방법을 보인다는 마크 업에 LinqDataSource을 사용하는 것입니다 ListView DataSource 속성을 통해가 아니라 ListView의 DataSourceID (ScottGu's sample - step 6에서와 같이). 그러나 나는 더 많은 작업이 가능하도록하기 위해 trick이 있음을 발견했다. 그래서 마크 업보다는 코드 숨김을 통해 LinqDataSource 쿼리를 정의 할 수있다. (참고 자료에 따르면 DataSource 컨트롤과 함께 작동하지만, 생각하지 않는다. 그 경우입니다).

아마도이 상황에서 어떤 도움이되지 않을 것입니다. 아마도 당신이 일종의 서비스를 호출했는데이 서비스가 작동하는 데 필요한 IQueryable 결과를 리턴하지 않을 것입니다.

<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(); 
} 

참고 관해서 MSDN 상태로 여기는

영문 마크 업 ... 어쨌든에서의 경우 당신이 관심입니다 QueryStringField 속성 :

의 모든 페이지가 검색 엔진에 의해 색인 된 인 경우이 속성을 설정하면 유용합니다. 이 은 컨트롤이 각 데이터 페이지에 대해 URL을 생성하기 때문에 발생합니다.

업데이트 : - this article and download the sample를 참조 가리키고 당신은 ObjectDataSource 컨트롤 대신 LinqDataSource 컨트롤을 사용하여 작업이를 얻을 수 있습니다. ObjectDataSource를 사용하는 것이 LinqDataSource 컨트롤을 사용하는 것만 큼 간단하지는 않지만, 적은 수의 마술 linq을 사용합니다 (대신 비즈니스/데이터 레이어 메서드에 매핑되는 마술 문자열의 힙을 사용합니다). 그리고 데이터 액세스 방법에 IEnumerable을 노출 할 수 있습니다 IQueryable 대신.

그래도 내 UI 마크 업에 모든 종류의 DataSource 컨트롤을 임베드하는 팬이 없습니다. (필자는 이것이 필요하다고 생각합니다.) 그래서 작은 응용 프로그램을 제외하고는 DataPager 컨트롤을 숨길 것입니다. 첫 번째 업데이트.

John 내가 알아챈 또 하나의 사실은 Asp.Net Mvc 응용 프로그램의 도우미 클래스로 개발 된 PagedList 클래스로 표준 Asp.Net 서버 컨트롤 (ViewState에 의존 함)과 결혼하려고한다는 것입니다.이 방법이 효과적 일 수는 있지만 더 간단한 경로가 필요할 수 있습니다.

+0

팁 주셔서 감사. Microsoft는 데이터 액세스 레이어와 응용 프로그램 레이어를 긴밀하게 연결하는 데 계속 매진하고 있습니다. – John

+1

고마워, 내가 살펴볼 게. 내가 필요로하는 것 같습니다. 나는 PagedList를 MVC의 것, Rob Conery의 것보다 더 많이 고려하지 않았다. PagedList를 찾기 전에, 저의 사람들은 List GetFoobars (string id, out TotalRowCount)와 같은 메소드를 사용하고있었습니다. 나에게 PagedList는 아웃을 사용하는 대신에 뭔가를하는 좋은 O-O 방법이었습니다. 결코 만족스럽지 않았습니다. – John

+0

더 간단한 경로는 MVC를 사용하는 것일뿐입니다. 그러나 팀은 아직이 사이트를 변환 할 준비가되어 있지 않습니다 (우리는 다른 곳에서 사용하기 시작했습니다). 내 개인적인 느낌은 MVC가 웹 사이트보다 훨씬 단순하지만 사이트 중 가장 단순하다는 것입니다. – John

0

John 저는 코드를 볼 수 있도록 여기에 약간의 개념 증명을했습니다. 나는 보풀이 없도록 이것을 가능한 한 기본으로 만들었습니다. 필요한 속성이 누락되어 있으면 수정하겠습니다. 눈에 띄었다

것 : 당신이 데이터 소스 객체 (XML, SQL, 액세스 ...) 사용하지 않을 때

  1. 데이터는 호출기의 OnPreRender 이벤트에 구속 될 필요가있다. 나는 입니다. 이것이 내가 가장 어려웠던 곳이기 때문에 이것이 당신의 문제라는 것을 확신하십시오.

  2. viewstate가가의 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

+0

이게 왜 더 복잡한 지 알겠습니다. 아마도 ICollection FooBarCollection과 같은 사용자 지정 컬렉션을 만들고 Count 메서드를 재정 의하여 전체 개수를 반환하도록 할 수 있습니다. 이것이 제대로 작동하는지 확신 할 수는 없지만 DataPager를 속여서 거기에 더 많은 데이터가 있다고 생각하도록 그런 일을해야 할 가능성이 높습니다. – Jerzakie

10

listview, datapager 및 linq 데이터 소스를 사용하는 SQL Server 페이징이 정확히 필요합니다. TotalRowCount는 읽기 전용입니다. 또한 전체 행 수를 설정하는 데 사용할 수있는 SetPageProperties 메서드가 있지만 저 또한 작동하지 않습니다.

그러나 나는이 방법으로 그것을 속일 수 있었다. 빈 항목 템플릿이있는 더미 숨겨진 목록 뷰가 있습니다. 호출기가 원래의 listview가 아닌 ​​더미리스트 뷰를 가리키고 있습니다. 그런 다음 더미 목록 뷰를 원본 데이터 소스에서와 같은 수의 항목이있는 더미 컬렉션에 바인딩해야합니다. 이렇게하면 호출기를 올바르게 렌더링 할 수 있습니다. 다음은 마크 업입니다.

<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(); 

이 100,000 레코드를 테스트 뒤에. 치료를해라.

+0

흥미로운 해결 방법. MVC 라우트로 지금 막 문제를 피할 수 있습니다 :-) – John

+0

이 답변은 정말 훌륭합니다 ... 빠르고 쉽고 데이터 페이저의 모든 장점을 얻을 수 있습니다. 고맙습니다 – clamchoda

관련 문제