在MVVM中的ViewModel中进行批量更改时,如何使用批处理(如BeginUpdate / EndUpdate)?

时间:2012-02-16 04:46:05

标签: c# .net wpf mvvm

在我使用MVVM的Silverlight应用程序中,我有一个图表(第三方ComponentOne),它绘制了大量数据,因此需要花费大量时间进行渲染。

我的ViewModel中有一个ObservableCollection(比如chartDataCollection),它绑定到图表的数据源。

在某些情况下,我在chartDataCollection中添加了100个项目,导致CollectionChange事件被触发100次并每次渲染图表需要花费大量时间。

C#中是否有我可以将这些更新组合在一起并在完成后只向用户通知一次?类似我们在Winforms世界中使用的东西,同时使用BeginUpdate向数据网格添加数据EndUpdate语句。

3 个答案:

答案 0 :(得分:2)

要实现的接口是INotifyCollectionChanged。此接口通过CollectionChanged事件与WPF绑定进行通信 - 此事件的参数(NotifyCollectionChangedEventArgs)可以报告已更改的批量项目。

实现这一目标的一种方法是实现自己的MyBatchObservableColleciton,派生或(更好)嵌入List(或任何其他适当的集合)。实现修改内聚集合的方法并记录所有这些变化。当您准备好将所有更改提交到WPF时,只需发送更改列表即可。以下是您可能会执行的操作的子集示例(仅对您的收藏集实施'添加' funcitonality):

class BatchObservableColleciton<T> : INotifyCollectionChanged, IEnumerable
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    private List<T> _list;
    private List<T> _addedItems;

    public BatchObservableColleciton( ) {
        _list = new List<T>( );
        _addedItems = new List<T>( );
    }

    public IEnumerator GetEnumerator( )
    {
        return _list.GetEnumerator( );
    }

    public void Add( T item )
    {
        _list.Add( item );
        _addedItems.Add( item );
    }

    public void commit( ) {
        if( CollectionChanged != null ) {
            CollectionChanged( this, new NotifyCollectionChangedEventArgs(
                NotifyCollectionChangedAction.Add, _addedItems ) );
        }
        _addedItems.Clear( );
    }

}

从未尝试过,但我认为这是要走的路。 Google for Custom&amp;的ObservableCollection。虽然不精确,但很少有实现。

答案 1 :(得分:0)

不使用ObservableCollection,而是使用IEnumerable模式的简单INotifyPropertyChanged属性。

private IEnumerable _ChartDataCollection;
public IEnumerable ChartDataCollection
{
    get
    {
        return _ChartDataCollection;
    }
    set
    {
        if (_ChartDataCollection != value)
        {
            _ChartDataCollection = value;
            NotifyPropertyChanged("ChartDataCollection");
        }
    }
}

答案 2 :(得分:0)

为什么不为所有更改使用单独的集合,然后合并两个集合并在完成后将其分配给您的公共集合?这只会触发一次PropertyChanged事件。

// Create a new List that contains objects from your Collection
var list = new List<SomeItem>(SomeCollection);

foreach(var item in newItems)
{
    // Add new items to list
}

// Reset collection w/ items from List
SomeCollection = new ObservableCollection<SomeItem>(list);