Silverlight,DataPager,RIA服务和智能分页

Cyl*_*Cat 13 silverlight-3.0 datapager wcf-ria-services

我仍然试图通过Silverlight和RIA Services来实现我的目标,当然还要从一些更"有趣"的东西开始,比如网格和智能分页.我可以连接到RIA Services(使用自行开发的ORM,而不是L2S或EF),在网格上获取数据,并连接到DataPager.域服务与本土ORM一起运行良好,至少对于查询而言.(仍在使用完整的CRUD.)但是,仍然存在问题:

  1. 为了支持用户应用程序,除了智能分页(仅运行查询显示所需的行)和分组之外,我还需要用户控制的排序和过滤.

  2. 到目前为止,我在DataGrid或DataPager中没有看到任何外部化这些功能的内容,因此可以将过滤,排序和分页参数传递给服务器以构建适当的查询.

  3. 数据集可能非常大; 我选择用于原型制作工作的我的表可以在一些客户中拥有多达35,000个条目,我确信还有其他更大的表格,我将不得不在某个时候处理.因此,"智能寻呼"方面至关重要.

我们欢迎您的想法,建议,指导和nerf砖.

Cyl*_*Cat 11

好吧,我已经花了几天杂草用这个,我想我已经掌握了它.

首先,一件重要的魔力.要使分页正常工作,无论当前查询返回多少项,寻呼机都必须知道总项数.如果查询返回所有内容,则项目计数显然是返回的项目数.对于智能分页,项目计数仍然是可用项目的总数,尽管查询仅返回显示的内容.通过过滤,每次过滤器更改时,甚至可用项的总数也会发生变化.

Silverlight Datapager控件具有名为ItemCount的属性.它是只读的,不能在XAML中数据绑定,或直接在代码中设置.但是,如果包含寻呼机的用户控件具有实现IPagedCollectionView的DataContext,则数据上下文对象必须使用PropertyChanged通知实现ItemCount属性,并且DataPager似乎自动选择它.

其次,我强烈推荐Brad Abrams 关于RIA服务的优秀系列博客文章,尤其是ViewModel 上的这篇博文.它包含了进行分页和过滤工作所需的大部分内容,尽管它缺少管理项目计数的关键部分.他的可下载示例还包含一个非常好的实现ModelViewViewModel(MVVM)的基本框架.谢谢你,布拉德!

所以这里是如何使项目计数工作.(此代码引用自定义ORM,而Brad的代码使用实体框架;在两者之间,您可以找到您在环境中需要的内容.)

首先,您的ORM需要支持获取记录计数,无论您是否使用过滤器.这是我的域名服务代码,可以为RIA服务提供计数:

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

[Invoke]
public int GetFilteredExamCount(string descriptionFilter)
{
    return Context.Exams.GetFilteredCount(descriptionFilter);
}
Run Code Online (Sandbox Code Playgroud)

注意[Invoke]属性.对于不返回Entity或Entity集合的任何DomainService方法,您需要这样做.

现在为ViewModel代码.当然,你需要一个ItemCount.(这是布拉德的例子.)

    int itemCount;
    public int ItemCount
    {
        get { return itemCount; }
        set
        {
            if (itemCount != value)
            {
                itemCount = value;
                RaisePropertyChanged(ItemCountChangedEventArgs);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

您的LoadData方法将运行查询以获取要在DataGrid中显示的当前行集.(这还没有实现自定义排序,但这是一个简单的添加.)

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

然后,回调方法运行查询以获取计数.如果没有使用过滤器,我们得到所有行的计数; 如果有过滤器,那么我们得到过滤行的计数.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个计数的回调方法:

void OnCountCompleted(InvokeOperation<int> op)
{
    ItemCount = op.Value;
    TotalItemCount = op.Value;
}
Run Code Online (Sandbox Code Playgroud)

设置了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
Run Code Online (Sandbox Code Playgroud)

条款"选择ROW_NUMBER()OVER(ORDER BY Description)作为rownum"是有趣的部分,因为还没有很多人使用"OVER".此子句在分配行号之前对"描述"上的表进行排序,并且在分配行号之前也应用过滤器.这允许外部SELECT在排序和过滤之后过滤行号.

所以它就是RIA Services和Silverlight中的带过滤功能的智能分页!

  • 当我遇到这样的问题时,框架应该做出共同的任务,在这种情况下,分页更容易让人感到担忧.使用RIA或不使用RIA这是个问题...... (3认同)