In my project we always deal with live data – that is data from the Data Model may change at any minute due to reasons like user interaction or an asynchronous change in what system the UI is modeling.
For the most part we want the UI to update automatically in response to the changes. INotifyCollectionChanged, INotifyPropertyChanged and data binding work very much to our advantage in dealing with this.
However if our data objects don’t define all the properties we need to bind to then we are left with a gap that needs to be filled.
Different strategies to fill that gap exists. The one we prefer is to use the Model-View-View Model pattern.
In this pattern we define a new object in the ViewModel which adapts and extends the object from the (Data) Model so it works great with the view.
For an example consider a ListBox which displays a set of Person objects. The Person class defines the obvious properties, Name, Age, Address, etc… Then visualize having a DataTemplate for the ListBox which displays the Name of each person.
Now lets add some functionality – lets say this ListBox is used in a dialog where the user is selecting people to e-mail. We could use ListBox multi-select, but our designer likes the look of CheckBoxes. So we add the CheckBox to the template, but what do we bind it to? We certainly don’t want to write code to walk the visual tree and manipulate the CheckBox instances directly.
Enter the ViewModel. We can define a new class, which we’ll call CheckablePerson. It contains a Person instance and exposes it via a property and also has an IsChecked property. We can now update the DataTemplate bindings and bind (two way) the CheckBox to the IsChecked property.
Now we can walk a collection of data objects to inspect/change the IsChecked state – much nicer. The only problem is how to go from our collection of Person objects to CheckablePerson objects – and that is the subject of this post.
We could do a one time conversion – walk the source collection and build the new collection. But going back to my initial statements this is live data – person objects may be added/removed at any time and we want the UI to update.
Enter ConvertingReadOnlyObservableCollection. It takes a source collection and a delegate. It then makes a shadow collection of a new type. It listens to INotifyCollectionChanged events to know when and how to update. It passes on INotifyPropertyChanged events. This makes it very easy to convert from Person to CheckablePerson. Source code for the class is attached.