WInRT introduces a new interface for collection change notification, IObservableVector, which means ObservableCollection no longer works with this framework. In this blog post I will show how you can use ObservableCollection, via a simple adapter, within you WInRT applications.
Developers are slowly starting to get their heads around the differences between the old (Silverlight, WPF, WP7) and the new - WinRT. Whilst the it has a familiar feel, with the UI defined in XAML and an API that is very similar to .NET, there are a great many differences. For an overview of some of these differences see:
- TweetSearch - A Cross platform Metro UI WinRT
- Morten Nielsen's blog series on WInRT vs. Silverlight differences
A number of developers have discovered that while WinRT has the
ObservableCollection class, when bound to the UI, lists / grids fail to update as items are added / removed. This is because while the same interfaces are being used for collections (
IEnumerable etc ...), there is a new interface for notification of collection changes,
IEnumerable its contents will be rendered in the UI, however it implements the 'old' interface for change notification -
The WinRT SDK samples include classes that implement
IObservableVector to demonstrate binding with collection change handling, however, what if you have some old code using
ObservableCollection that you want to port over? Or, what if you want to code-share between Silverlight and WInRT?
A few days ago I saw a blog post by Avi Pilosof where he created a class that implements both the INotifyCollectionChanged and IObservableVector interfaces. This will certainly do the job, however there is a simpler way ...
Using the Gang of Four Adapter pattern, we can create a class which wraps
ObservableCollection, to implement
IObservableVector extends various list interfaces (ILIst etc ...) so we have to implement these on
ObservableCollectionShim via straight-through adapter methods ...
Now, the interesting part! The change notification is implemented by handling
CollectionChanged events, and re-emitting them as
Note, there does not seem to be an equivalent for
NotifyCollectionChangedAction.Move, however, I am pretty sure
ObservableCollection never raises that change type anyway!
We can now make use of our 'shim' class within a view-model as follows:
However, if we were using this view-model within a cross-platform application, this would still cause problems, because
IObservableCollection does not exist in Silveright / WPF. A more elegant solution is to wrap the
ObservableCollection in the shim class within a value converter. Firstly, we need a way to create a shim without specifying the generic type argument (
IValueConverter is not strongly typed, your bound values are presented as the type 'object'):
This can then be used within a value converter as follows:
This allows us to adapt an
ObservableCollection for use with WinRT simply by applying a value-converter within the View:
A nice side-effect of this approach is that if we replace the
ObservableCollection within our view-model with a new instance, the binding framework will take care of creating a new 'shim' via the value converter.
This technique allows us to write cross-platform view-models using
ObservableCollection for our collections of objects.
You can download the sourcecode with a simple example here: ObservableCollectionShim.zip
Regards, Colin E.