Thursday, December 01, 2011

ObservableVector as a replacement for ObservableCollection in Metro-style apps

For those of you who have had previous experience in making WPF and Silverlight applications you are probably familiar with the ObservableCollection<T> class. This represents a list of items (implementing IList<T>) whilst also raising the INotifyCollectionChanged.CollectionChanged event whenever items are added, removed or moved within the collection. When such collections are databound to the various list controls in WPF and Silverlight the UI will automatically update to reflect any changes.

ObservableCollection<T> and Metro-Style Apps

If you have followed the same technique when writing Windows 8 Metro-style apps you will have found that this no longer works. There are a couple of reasons for this behaviour,

  1. In the Developer Preview version of Windows 8 the INotifyPropertyChanged interface is duplicated in both the System.ComponentModel and Windows.UI.Xaml.Data namespaces. Whilst ObservableCollection<T> implements the former, the new Metro XAML framework uses the latter.
  2. Rather than INotifyCollectionChanged as implemented by ObservableCollection<T>, WinRT uses the IObservableVector<T> interface.

Observable Collections in Metro-Style Apps

Whilst this issue is likely to be addressed prior to release of Windows 8, for the time being there are a few workarounds.

  1. The Windows 8 SDK Data Binding sample includes an ObservableVector class that takes an existing object that implements INotifyCollectionChanged, and wraps it in an IObservableVector<T> implementation.
  2. Colin Eberhardt has posted a similar solution on his blog.
  3. Avi Pilosof has taken a slightly different approach by deriving a new class from ObservableCollection<T>, implementing both INotifyCollectionChanged and IObservableVector<T>.

Whilst these solve the problem, they all involve wrapping the existing ObservableCollection<T> class, resulting in events being raised for both the old and new approaches. This is ideal for cases where you wish to write interoperable code for both existing and Metro applications, but is an added overhead when you are natively writing a new Windows 8 application.

A Metro-Designed Observable Collection Class

In response to this I have written a ground-up ObservableVector<T> class for use in Windows 8 Metro-style applications that does not have the overhead of an underlying ObservableCollection<T>. The code has been released as part of the freely available Cocoon framework. You can use this class by creating a new instance directly,

IList<Person> list = new ObservableVector<Person>();
list.Add(new Person("Andrew", "Wilkinson"));


or by deriving a custom class,



public class PersonCollection : ObservableVector<Person>
{
    ...
}


It is important to note however that in the current Windows Developer Preview there is a bug which means that databinding only works correctly to lists when the implement ObservableVector<object> rather than strongly typed collections. This is likely to change in the future.


In both cases the behaviour is designed to match that expected by WPF and Silverlight developers. There are a small number of subtle differences with respect to the previous ObservableCollection<T> class,



  1. Since IObservableVector<T> does not have the same concept of moving items it does not implement the Move() method. Instead you should remove the item and then add it to its new place in the collection.

  2. The constructor of the ObservableVector<T> class optionally accepts an IList<T> that is wrapped by the implementation rather than copied internally – the reason for this will become apparent in later posts.

  3. Currently no attempts are made to stop VectorChanged event handlers from modifying the original collection.

Summary


In conclusion, the Cocoon framework provides an IObservableVector<T> implementation specifically designed from the ground-up for Metro applications. The code is freely available for download from the Cocoon CodePlex site (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).


Next time I will discuss data virtualisation and the IVirtualizingVector interface.

Post a Comment