Search code examples
performancemvvmitemscontrolitemssource

ItemsControl.ItemsSource MVVM performance


I have an (non-virtualized) ItemsControl that binds its ItemsSource to a ObeservableCollection of ViewModel instances. Now once the large amount Model instances is loaded all the ViewModel complemnents needs to be added to that ObservableCollection. How can I add a large amount of ViewModels without making the UI Thread hang?

I suppose the UI Thread hangs because each time a new item is added the ItemsControl needs to update itself and does layout etc. over and over again.

  • Should I suspend the binding add all items and then resume? If so, how?
  • Should I override the ObservableCollection to implement an AddRange so only 1 CollectionChanged Event is fired for adding multiple items? Or alternatively just replace the whole collection?
  • Or is it better to add each items separately and call Dispatcher.Invoke for each item separately? So I would unblock frequently.

How do you handle large dynamic lists that can not be virtualized?


Solution

  • You can create a a class derived from ObservableCollection which allows you to temporarily suspend CollectionChanged events like this:

    public class SuspendableObservableCollection : ObservableCollection
    {
        private bool suspended;
    
        public bool Suspended 
        {
            get
            {
                return this.suspended;
            }
            set
            {
                this.suspended = value;
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(
                    NotifyCollectionChangedAction.Reset));
            }
        }
    
        protected override void OnCollectionChanged(
            NotifyCollectionChangedEventArgs args)
        {
           if (!Suspended)
           {
               base.OnCollectionChanged(args);
           }
        }
    }