2011-07-22 49 views
2

我有一个使用Telerik RadGridView控件和Caliburn.Micro MVVM框架实现的应用程序。由于一些性能问题,我需要实现Telerik VirtualQueryableCollectionView来代替正在使用的直接控件到ObservableCollection绑定。原始代码已将RadGridView的ItemsSouce属性绑定到视图模型的Prices属性。我不得不消除结合,这在后台代码:使用MVVM模式实现Telerik VirtualQueryableCollectionView

public PricingView(PricingViewModel vm) 
{ 
    InitializeComponent(); 

    var dataView = new VirtualQueryableCollectionView() 
         { LoadSize=20, VirtualItemCount = vm.Prices.Count }; 
    dataView.ItemsLoading += (sender, e) => 
     { 
      var view = sender as VirtualQueryableCollectionView; 
      if (dataView != null) 
      { 
       view.Load(e.StartIndex, vm.Prices.Skip(e.StartIndex).Take(e.ItemCount)); 
      } 
     }; 
    this.PricesGridView.ItemsSource = dataView; 
} 

因为这个代码仅与特定的用户界面功能,交易和它特定的视图实现,我很舒服,这个代码属于代码 - 而不是ViewModel,因为它将与ViewModel中的VirtualQueryableCollectionView引用相背离。我不满意的部分是将ViewModel的引用传递给View的构造函数。是否有一种很好的方法在代码隐藏中获取引用,而无需在构造函数中传递引用?

还是有更好的方法来做到这一切吗?

回答

0

不知道“性能问题”是什么意思,但我会假设这意味着当您从UI线程填充集合时,它会阻塞应用程序足够长的时间,它看起来没有响应。

有两种常见的解决方案。首先是简单地从后台线程填充您的收藏。

简单的实现是简单地将加载推送到ThreadPool线程,然后使用Dispatcher将调用添加到ObservableCollection到UI线程的项目。

更好的方法(根本不涉及ViewModel)是使用asynchronous bindings.将回退配置为某个值,该值指示您正在加载的用户。有时(取决于具体情况),您可以使用PriorityBinding逐渐填充您的用户界面。

其他替代方法是在显示splash screen时预先加载并缓存您的数据。它们在WPF中有点不同,它不像老式的“在我工作时显示这个表单稍微显示一下,然后显示winform的主要形式”模式。当然,总是有经典的数据分页。它很难编码,但很有效。其实,我应该在UI中说出它的强悍。现在在代码中很容易(database.Skip(pageNumber * pageSize).Take(pageSize))。

+0

感谢您的回答,'性能问题'我引用了它进行数据绑定的时间。 –

+0

我包含的代码片段通过将数据从'集合'按需'绑定到控件上来解决了我遇到的问题。实际上,代码使用数据集合上的Skip()和Take()扩展方法,就像您在答案的最后一行所做的一样。我看到我没有提到我的环境是Silverlight。 –

3

我的应用程序是用MVVM Light实现的,在我的情况下,我在ViewModel中使用了VirtualQueryableCollectionView类代替View。

我这样做是因为我认为这个类与ObservableCollection非常相似,尽管它不是核心类的一部分。 实际上,VirtualQueryableCollectionView不限于Telerik控件,而是其他许多标准控件,如ListView

在我的情况下,获取是在模型中实现的。

void MainViewModel() 
{ 
    this.Traces = new VirtualQueryableCollectionView<MyEntityClass>() 
    { 
     // ViewModel also manages the LoadSize 
     LoadSize = this.PageSize, 
     VirtualItemCount = myModel.TotalCount 
    }; 
    this.Traces.ItemsLoading += (s, args) => 
    { 
     this.Traces.Load(args.StartIndex, 
         myModel.FetchRange(args.StartIndex, args.ItemCount)); 
    }; 
} 
相关问题