13

我仍在尝试使用 Silverlight 和 RIA 服务,当然还从一些更“有趣”的东西开始,例如网格和智能分页。我可以连接到 RIA 服务(使用自制的 ORM,而不是 L2S 或 EF),在网格上获取数据,并连接到 DataPager。域服务与本土 ORM 配合得很好,至少在查询方面是这样。(仍在研究完整的 CRUD。)但是,仍然存在问题:

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

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

  3. 数据集可能非常大;我为原型设计工作选择的表在某些客户那里最多可以有 35,000 个条目,而且我确信在某些时候我还必须处理其他更大的表。所以“智能寻呼”方面是必不可少的。

欢迎提出想法、建议、指导和 nerf 砖块。

4

3 回答 3

11

好的,我已经用这个在杂草中度过了几天,我想我已经掌握了它。

首先,一个重要的魔法。为了使分页正常工作,分页器必须知道总项目数,无论当前查询返回了多少项目。如果查询返回所有内容,则项目计数显然是返回的项目数。对于智能分页,项目计数仍然是可用项目的总数,尽管查询只返回显示的内容。使用过滤器,每次过滤器更改时,甚至可用项目的总数都会更改。

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

其次,我强烈推荐 Brad Abrams关于 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

子句“select ROW_NUMBER() OVER (ORDER BY Description) as rownum”是有趣的部分,因为还没有多少人使用“OVER”。此子句在分配行号之前按说明对表进行排序,并且在分配行号之前也应用过滤器。这允许外部 SELECT 在排序和过滤之后过滤行号。

就是这样,在 RIA 服务和 Silverlight 中使用过滤的智能分页!

于 2010-02-21T16:09:55.773 回答
4

这是快速而肮脏的解决方案(我选择了):

只需将您DomainDataSource的 ViewModel 移至您的视图模型!完毕!

可能对可测试性不太好,可能还有一些我还没有发现的其他限制,但我个人并不关心这一点,直到 出现更好的东西

在您的 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。感谢上述链接页面中的“弗朗索瓦”。在看到您的评论之前,我什至没有意识到我可以将 DomainDataSource 从 XAML 中取出!

于 2010-08-14T03:38:35.557 回答
0

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

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

于 2010-08-14T03:25:01.497 回答