好吧,我已經花了幾天在這雜草叢生,我想我已經掌握了它。
首先,一塊重要的魔法。爲使分頁正常工作,無論當前查詢返回多少項目,分頁器都必須知道總項目數。如果查詢返回所有內容,則項目計數顯然是返回的項目數量。對於智能分頁,項目計數仍然是可用項目的總數,儘管查詢僅返回顯示的內容。通過過濾,即使每次過濾器更改時,可用項目的總數也會發生變化。
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中,過濾功能就是智能分頁!
當我遇到類似這樣的問題時,應該創建通用任務的框架,在這種情況下,分頁更容易,這有點令人擔憂。要使用RIA或不使用RIA,這是個問題... – sipwiz 2010-04-20 14:15:17
那麼,這是一個尚未解決的問題。 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