Click here to Skip to main content
13,300,687 members (50,875 online)
Click here to Skip to main content
Add your own
alternative version


18 bookmarked
Posted 4 Sep 2013

ItemsContainer: Simple ObservableCollection thread safety

, 4 Sep 2013
Rate this:
Please Sign up or sign in to vote.
ItemsContainer allows easy sorting and updating of ObservableCollections from async or parallel threads.


The ObservableCollection does not work very well in a multi-threaded environment. After it's bound to the UI, it can't be replaced with a new one, even if it's on a notify-property (INotifyPropertyChanged). This requires the user to Clear its contents and Add each new item, triggering a notification message each time. All this has to be done on the UI thread.

Notify-properties, on the other hand, are insulated from the UI. They can be set from any thread and the associated Binding will update the UI without any problems.


Therefore to insulate an ObservableCollection from the UI, it can be put inside a container object which is set on a notify-property. Wpf will make updates to the new ObservableCollection inside a container object regardless of the thread. 

ItemsContainer class:

public class ItemsContainer<T> : IEnumerable<T>
  public ItemsContainer()
     this.Items = new ObservableCollection<T>();

  public ItemsContainer(IEnumerable<T> items)
     this.Items = new ObservableCollection<T>(items);

  public ObservableCollection<T> Items { get; private set; }


This generic ItemsContainer makes it easy to sort and update items. Just create a new one with the updated items, and set it on a notify-property.

Async ItemsContainer example

Here's an example of a FolderItem class that puts child items in an ItemsContainer. This example sorts an ObservableCollection async.


public class FolderItem : FileFolderBase, IItemsContainer<FileFolderBase>

  #region Container INotifyPropertyChanged Property

  private ItemsContainer<FileFolderBase> _Container;

  public ItemsContainer<FileFolderBase> Container
     get { return this._Container; }
        if (this._Container != value)
           this._Container = value;



  public Task SortAsync(SortKind kind)
     var t = Task.Factory.StartNew(() => 

     return t;

  public void Sort(SortKind kind)
     List<FileFolderBase> items = new List<FileFolderBase>();

     var folders = from f in this.Container.Items
              where f is FolderItem
              orderby f.Name
              select f;

     var files = from f in this.Container.Items
              where f is FileItem
              orderby f.Name
              select f;

     switch (kind)
        case SortKind.NameAscending:
        case SortKind.NameDescending:

     // this will update ObservableCollection items from any thread
     this.Container = new ItemsContainer<FileFolderBase>(items);



 <TabItem Header="ListBox" >
    <ListBox ItemsSource="{Binding FileFolderList.Container.Items}">
             <MenuItem Header="Sort Ascending" Command="{Binding SortListAscending}" />
             <MenuItem Header="Sort Descending" Command="{Binding SortListDescending}" />

View model command handler:

this.SortListAscending.CanExecuteCommand = 
      () => this.ListSortKind != SortKind.NameAscending;

this.SortListAscending.ExecuteCommand = async () =>
  await this.FileFolderList.SortAsync(SortKind.NameAscending);
  this.ListSortKind = SortKind.NameAscending;

Above, a new ItemsContainer and ObservableCollection are created with the updated items and set on the Container notify-property on a non-UI thread. Wpf binds the ListBox ItemsSource to the new ObservableCollection without any problems.

Parallel ItemsContainer example

The ItemsContainer makes parallel processing much simpler. Here's an example where a tree of FolderItems is sorted using Parallel.ForEach.

WpfItemsContainer screen shot:


FolderItem code:

public Task SortDescendantItemsAndSelfAsync(SortKind kind)
 Task t = Task.Factory.StartNew(() =>
       var folders = this.GetDescedantFoldersAndSelf();
       Parallel.ForEach(folders, folder =>

 return t;


<TabItem Header="TreeView" >
<TreeView ItemsSource="{Binding FileFolderTree.Container.Items}"



         <MenuItem Header="Open folders" Command="{Binding OpenFolders}" />
         <MenuItem Header="Close folders" Command="{Binding CloseFolders}" />
         <Separator />
         <MenuItem Header="Sort Ascending" Command="{Binding SortTreeAscending}" />
         <MenuItem Header="Sort Descending" Command="{Binding SortTreeDescending}" />

View model command handler: 

this.SortTreeAscending.CanExecuteCommand = 
                  () => this.TreeSortKind != SortKind.NameAscending;

this.SortTreeAscending.ExecuteCommand = async () =>
  await this.FileFolderTree.SortDescendantItemsAndSelfAsync(SortKind.NameAscending);
  this.TreeSortKind = SortKind.NameAscending;

Obviously, it would be much more difficult sorting each FolderItems' child items on parallel threads then updating each FolderItem's ObservableCollection from the UI thread. It would also make the code more difficult to follow.


Although the ItemsContainer is a simple idea, it's an effective way to eliminate ObservableCollection thread safety problems.

Benefits of ItemsContainer:

  • Insulates the OC from the UI.
  • OC sorting and updates can be done from any thread. 
  • Makes asynchronous and parallel operations simpler and easier: less code to keep track of.
  • No need to keep track of the UI Dispatcher for updates.
  • Purer MVVM: The UI Dispatcher is actually part of the View and is out of place in the ViewModel. With ItemsContainer, the UI thread is irrelevant which better separates the ViewModel from the View.
  • No illegal thread call exceptions (InvalidOperationException): When OC is connected to the UI, one must ensure all methods that affect it (directly or indirectly) are called from the UI thread. This can get complicated, require additional documentation and potentially trigger illegal thread call exceptions. Theses issues are eliminated using ItemsContainer.
  • More efficient updates: Updating an OC with a Clear call and Add call for each item has a lot of notification overhead. ItemsContainer creates a new OC passing the items directly to the constructor.
  • One can use Wpf's ObservableCollection class without any modifications. 


  • The Binding path is longer: It must go to the ItemsContainer property and then OC Items property.
  • The ItemsContainer/Items relationship could cause confusion to programmers unfamiliar with the code pattern. 
  • An OC property, by itself, can have a name reflective of the items it holds. Although one can name the ItemsContainer, it's not possible to rename the Items OC property without creating a new class.

Points of Interest 

When working with trees, I find it's a lot easier using tree iterators. I've created a simple extensible class that uses a recursive IEnumerable<T> implement that iterates all tree branches and leaves.


public class ItemsContainerTreeIterator<TItem, TItemFilter> : TreeIteratorBase<TItemFilter>
  where TItem : class
  where TItemFilter : class
  public ItemsContainerTreeIterator(IItemsContainer<TItem> ancestor)
     : base(ancestor)

  protected override System.Collections.IEnumerable GetParentEnumerable(object currentParent)
     IItemsContainer<TItem> parent = (IItemsContainer<TItem>)currentParent;

     // get ItemsContainer which implements IEnumerable
     var container = parent.GetItemsContainer();

     return container;

  protected override object GetChildAsParent(object Child)
     IItemsContainer<TItem> container = Child as IItemsContainer<TItem>;

     // return object if child is parent; null if child has no child items
     return container;

ItemsContainerTreeIterator in action (from FolderItem):

public FolderItem[] GetDescendantFolders()
 ItemsContainerTreeIterator<FileFolderBase, FolderItem> it = 
    new ItemsContainerTreeIterator<FileFolderBase, FolderItem>(this);

 return it.ToArray();


  • 2013/9/4: Original article.
  • 2013/9/4: Added Conclusion: benefits and drawbacks. 


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ron Waller
Canada Canada
Programming enthusiast. I work with C#, WPF, MVVM, F#, ASP.NET, javascript, jQuery, Css.

You may also be interested in...

Comments and Discussions

QuestionVote of 5 Pin
GanesanSenthilvel9-Sep-13 6:28
memberGanesanSenthilvel9-Sep-13 6:28 
GeneralMy vote of 5 Pin
Volynsky Alex5-Sep-13 1:31
memberVolynsky Alex5-Sep-13 1:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171207.1 | Last Updated 4 Sep 2013
Article Copyright 2013 by Ron Waller
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid