好吧,我已经花了几天在这杂草丛生,我想我已经掌握了它。
首先,一块重要的魔法。为使分页正常工作,无论当前查询返回多少项目,分页器都必须知道总项目数。如果查询返回所有内容,则项目计数显然是返回的项目数量。对于智能分页,项目计数仍然是可用项目的总数,尽管查询仅返回显示的内容。通过过滤,即使每次过滤器更改时,可用项目的总数也会发生变化。
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