Как использовать пакетную обработку, что-то вроде BeginUpdate / EndUpdate, при массовых изменениях в ViewModel в MVVM? - PullRequest
3 голосов
/ 16 февраля 2012

В моем приложении Silverlight, использующем MVVM, у меня есть диаграмма (ComponentOne стороннего производителя), которая отображает огромные данные, поэтому для ее отрисовки требуется много времени.ViewModel, который привязан к источнику данных диаграммы.

В некоторых сценариях я добавляю 100s элементов в chartDataCollection, что приводит к тому, что событие CollectionChange запускается 100 раз и отображает диаграмму каждый раз, что занимает много времени.

Есть ли в C # способ сгруппировать эти обновления и уведомить пользовательский интерфейс только один раз, когда я закончу? Что-то похожее на то, что мы привыкли в мире Winforms при добавлении данных в сетку данныхиспользуя операторы BeginUpdate и EndUpdate.

Ответы [ 3 ]

2 голосов
/ 16 февраля 2012

Интерфейс для реализации - INotifyCollectionChanged. Этот интерфейс взаимодействует с привязкой WPF через событие CollectionChanged - аргумент этого события (NotifyCollectionChangedEventArgs) может сообщать пакеты элементов, которые были изменены.

Один из способов сделать это - реализовать свой собственный MyBatchObservableColleciton, получить или (лучше) встроить List (или любую другую подходящую коллекцию). Реализуйте методы для изменения коллекции Innter и запишите все эти изменения. Когда вы будете готовы зафиксировать все свои изменения в WPF, просто отправьте список изменений. Вот пример того, что вы можете сделать (реализуя только функцию «Добавить» в вашу коллекцию):

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 для Custom & ObservableCollection. Хотя это и не точно, существует несколько реализаций.

0 голосов
/ 16 февраля 2012

Почему бы не использовать отдельную коллекцию для всех изменений, а затем объединить две коллекции и назначить их в свою публичную коллекцию, как только вы закончите? Это вызовет событие 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);
0 голосов
/ 16 февраля 2012

Вместо использования ObservableCollection используйте простое свойство IEnumerable с использованием шаблона INotifyPropertyChanged.

private IEnumerable _ChartDataCollection;
public IEnumerable ChartDataCollection
{
    get
    {
        return _ChartDataCollection;
    }
    set
    {
        if (_ChartDataCollection != value)
        {
            _ChartDataCollection = value;
            NotifyPropertyChanged("ChartDataCollection");
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...