2010-02-18 63 views
13

我仍然试图通过Silverlight和RIA Services让自己的脚步稳固,当然还有一些比较“有趣”的东西,比如网格和智能分页。我可以连接到RIA服务(使用本地ORM而不是L2S或EF),在网格上获取数据并连接到DataPager。至少在查询时,域服务与本土ORM运行良好。 (仍然工作在完整的CRUD)。然而,仍然存在问题:Silverlight,DataPager,RIA Services和智能分页

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

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

  3. 数据集可能相当大;我选择的用于原型设计工作的桌子在一些客户中可以拥有多达35,000个参赛作品,并且我确信还有其他表格可能会更大,我不得不在某些时候处理这​​些表格。所以“智能寻呼”方面至关重要。

想法,建议,指导和nerf砖都欢迎。

回答

11

好吧,我已经花了几天在这杂草丛生,我想我已经掌握了它。

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

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中,过滤功能就是智能分页!

+3

当我遇到类似这样的问题时,应该创建通用任务的框架,在这种情况下,分页更容易,这有点令人担忧。要使用RIA或不使用RIA,这是个问题... – sipwiz 2010-04-20 14:15:17

+0

那么,这是一个尚未解决的问题。 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

4

这里的快速和肮脏的解决方案(我去了):

只动DomainDataSource您的视图模型!完成!

对于可测试性和可能还有一些其他限制我可能还没有发现,但我个人并不在乎直到something better comes along

您的视图模型里面只是实例化数据源:

// 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中取出,直到我看到您的评论!

相关问题