2010-02-18 61 views
13

我仍然試圖通過Silverlight和RIA Services讓自己的腳步穩固,當然還有一些比較「有趣」的東西,比如網格和智能分頁。我可以連接到RIA服務(使用本地ORM而不是L2S或EF),在網格上獲取數據並連接到DataPager。至少在查詢時,域服務與本土ORM運行良好。 (仍然工作在完整的CRUD)。然而,仍然存在問題:Silverlight,DataPager,RIA Services和智能分頁

  1. 爲了支持用戶應用程序,我需要用戶控制的排序和過濾,除了智能分頁(僅運行行查詢需要顯示)和分組。

  2. 到目前爲止,我沒有在DataGrid或DataPager中看到任何可以將這些功能外化的過程,因此可以將過濾,排序和分頁參數傳遞給服務器以構建適當的查詢。

  3. 數據集可能相當大;我選擇的用於原型設計工作的桌子在一些客戶中可以擁有多達35,000個參賽作品,並且我確信還有其他表格可能會更大,我不得不在某些時候處理這​​些表格。所以「智能尋呼」方面至關重要。

想法,建議,指導和nerf磚都歡迎。

回答

11

好吧,我已經花了幾天在這雜草叢生,我想我已經掌握了它。

首先,一塊重要的魔法。爲使分頁正常工作,無論當前查詢返回多少項目,分頁器都必須知道總項目數。如果查詢返回所有內容,則項目計數顯然是返回的項目數量。對於智能分頁,項目計數仍然是可用項目的總數,儘管查詢僅返回顯示的內容。通過過濾,即使每次過濾器更改時,可用項目的總數也會發生變化。

Silverlight Datapager控件具有一個名爲ItemCount的屬性。它是隻讀的,不能在XAML中進行數據綁定,或者直接在代碼中進行設置。但是,如果包含分頁器的用戶控件具有實現IPagedCollectionView的DataContext,那麼數據上下文對象必須實現帶有PropertyChanged通知的ItemCount屬性,並且DataPager似乎會自動選擇它。

其次,我強烈推薦Brad Abrams出色的series of blog posts on RIA Services,尤其是ViewModel。它包含了大部分進行分頁和過濾工作所需的內容,儘管它缺少管理項目數的關鍵部分。他的可下載示例還包含用於實現ModelViewViewModel(MVVM)的非常好的基本框架。謝謝布拉德!

所以這裏是如何使項目計數工作。 (此代碼是指自定義的ORM,而Brad的代碼使用實體框架;在這兩者之間,您可以根據自己的環境計算出您需要的值)。過濾。這裏是我的域名服務代碼,使數提供給RIA服務:

[Invoke] 
public int GetExamCount() 
{ 
    return Context.Exams.Count(); 
} 

[Invoke] 
public int GetFilteredExamCount(string descriptionFilter) 
{ 
    return Context.Exams.GetFilteredCount(descriptionFilter); 
} 

注[調用]屬性。對於任何不返回實體或實體集合的DomainService方法,您都需要此方法。

現在爲ViewModel代碼。當然,你需要一個ItemCount。 (這是來自Brad的例子。)

int itemCount; 
    public int ItemCount 
    { 
     get { return itemCount; } 
     set 
     { 
      if (itemCount != value) 
      { 
       itemCount = value; 
       RaisePropertyChanged(ItemCountChangedEventArgs); 
      } 
     } 
    } 

您的LoadData方法將運行查詢以獲取要在DataGrid中顯示的當前行集。 (這不實現自定義排序還沒有,但是這是一個簡單的加法。)

EntityQuery<ExamEntity> query = 
     DomainContext.GetPagedExamsQuery(PageSize * PageIndex, PageSize, DescriptionFilterText); 
    DomainContext.Load(query, OnExamsLoaded, null); 

回調方法然後運行查詢來獲取計數。如果沒有使用過濾器,我們得到所有行的計數;如果有一個過濾器,那麼我們得到過濾行的計數。

private void OnExamsLoaded(LoadOperation<ExamEntity> loadOperation) 
{ 
    if (loadOperation.Error != null) 
    { 
     //raise an event... 
     ErrorRaising(this, new ErrorEventArgs(loadOperation.Error)); 
    } 
    else 
    { 
     Exams.MoveCurrentToFirst(); 
     if (string.IsNullOrEmpty(DescriptionFilterText)) 
     { 
      DomainContext.GetExamCount(OnCountCompleted, null); 
     } 
     else 
     { 
      DomainContext.GetFilteredExamCount(DescriptionFilterText, OnCountCompleted, null); 
     } 
     IsLoading = false; 
    } 
} 

還有用於計數的回調方法:

void OnCountCompleted(InvokeOperation<int> op) 
{ 
    ItemCount = op.Value; 
    TotalItemCount = op.Value; 
} 

隨着ItemCount中集,DataPager控件將它拾起,我們有分頁與過濾和返回只記錄到智能查詢被顯示!

LINQ使用.Skip()和.Take()方便查詢。用原始的ADO.NET做這件事很難。我學會了如何通過拆分LINQ生成的查詢來完成此操作。

SELECT * FROM 
    (select ROW_NUMBER() OVER (ORDER BY Description) as rownum, * 
    FROM Exams as T0 WHERE T0.Description LIKE @description) as T1 
WHERE T1.rownum between @first AND @last ORDER BY rownum 

的條款 「選擇ROW_NUMBER)OVER(ORDER BY說明)(爲ROWNUM」 是有趣的部分,因爲沒有多少人使用 「OVER」 呢。此子句在分配行號之前對「說明」中的表進行排序,並且在分配行號之前也應用過濾器。這允許外部SELECT在排序和過濾之後過濾行號。

因此,在RIA Services和Silverlight中,過濾功能就是智能分頁!

+3

當我遇到類似這樣的問題時,應該創建通用任務的框架,在這種情況下,分頁更容易,這有點令人擔憂。要使用RIA或不使用RIA,這是個問題... – sipwiz 2010-04-20 14:15:17

+0

那麼,這是一個尚未解決的問題。 RIA Services for Silverlight 3和VS 2008幾乎已經死了,現在可用的是公開測試版,它不會被增強,並且只會在12月份之前得到支持。所以RIA Services for Silverlight 4和VS 2010是可選的。它現在處於RC2狀態;一旦達到發佈狀態,我會立即檢查它。 FWIW,Brad Abrams說讓Silverlight datagrid做分頁,但仍然存在自定義過濾的問題,這就是最初爲我殺死RIA Services的原因。我們必須能夠在服務器上進行過濾。 – 2010-04-20 14:59:58

4

這裏的快速和骯髒的解決方案(我去了):

只動DomainDataSource您的視圖模型!完成!

對於可測試性和可能還有一些其他限制我可能還沒有發現,但我個人並不在乎直到something better comes along

您的視圖模型裏面只是實例化數據源:

// Feedback DataSource 
_dsFeedback = new DomainDataSource(); 
_dsFeedback.DomainContext = _razorSiteDomainContext; 
_dsFeedback.QueryName = "GetOrderedFeedbacks"; 
_dsFeedback.PageSize = 10; 
_dsFeedback.Load(); 

,並提供一個可綁定屬性:

private DomainDataSource _dsFeedback { get; set; } 
public DomainDataSource Feedback 
{ 
    get 
    { 
     return _dsFeedback; 
    } 
} 

和你DataPager的添加到您的XAML:

<data:DataPager Grid.Row="1" 
        HorizontalAlignment="Stretch" 
        Source="{Binding Feedback.Data}" 
        Margin="0,0,0,5" /> 

    <data:DataGrid ItemsSource="{Binding Feedback.Data}"> 


PS。感謝上面鏈接頁面的'Francois'。我甚至沒有意識到我可以將DomainDataSource從XAML中取出,直到我看到您的評論!