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

时间:2010-02-18 12:59:24

标签: silverlight-3.0 wcf-ria-services datapager

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

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

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

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

  4. 欢迎提出想法,建议,指导和nerf砖。

3 个答案:

答案 0 :(得分:11)

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

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

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

其次,我强烈推荐布拉德艾布拉姆斯出色的series of blog posts on RIA Services,特别是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);
}

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

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

    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 Description)作为rownum”是有趣的部分,因为还没有很多人使用“OVER”。此子句在分配行号之前对“描述”上的表进行排序,并且在分配行号之前也应用过滤器。这允许外部SELECT在排序和过滤后对行号进行过滤。

因此,在RIA Services和Silverlight中进行智能分页和过滤!

答案 1 :(得分:4)

这是快速而肮脏的解决方案(我去过):

将您的DomainDataSource移至ViewModel!完成!

对于可测试性可能并不是很好,可能还有其他一些我尚未发现的限制,但我个人并不关心直到 something better comes along

在ViewModel中只是实例化数据源:

// 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中取出来!

答案 2 :(得分:0)

这是一篇有趣的文章,从2010年5月开始,关于框架中此类功能可能的未来支持。

http://www.riaservicesblog.net/Blog/post/WCF-RIA-Services-Speculation-EntityCollectionView.aspx