Freigeben über


Observable Collection Projections (Synchronized MVVM Collections)

(Category: Rambling)
Sometimes it’s funny how the same simple problem comes up over and over again, and people immediately solve it over and over again. Of course usually I only notice it when I am one of those people.

Some time back I found myself writing a INotifyCollectionChanged collection synchronizer for working around a ModelItemCollection bug in workflow designer. The bug we were working around was nothing to do with change notification at all. The workaround was basically to create a ValueConverter which would create a new Collection C from the original ModelItemCollection M, and the workaround part is that we could redefine .Contains(item) to work for the case item == null.

Where change notification comes in to all that is that the listbox we bind will handle INotifyCollectionChanged notifications from the collection it is bound to, and to get change notification for C, we need to make C ‘forward’ all the change notifications from M.

So why do I return to the subject?

Today I was chatting about a problem with some similarities. Our devs are working on another app which has collections with change notification. In several places in the app there are generative functions which achieve something like this (pseudocode, Linq select):

this.collectionViewModelForWPFBinding binds to autoupdating select query on collection: this.realBackingCollection.Select((item) => CreateViewModelFromItem(item));

“Hang on, this looks like the kind of thing that’s generally useful, I wonder if it’s in the framework already?”

Do some reflector diving… There’s several classes which sound fairly general in nature and react to NotifyCollectionChangedEventArgs. Including something called CompositeCollectionView, which is for implementing a CollectionView for CompositeCollection? Interesting. I didn’t know about either of these classes until today.

CompositeCollection class: Enables multiple collections and items to be displayed as a single list.
CollectionView class: Represents a view for grouping, sorting, filtering, and navigating a data collection.

Neither of them is what I’m looking for though. Next we try the intertubes… hm, apparently in general this really is a popular problem. Here are a few investigations people have made:

https://www.thesilvermethod.com/Default.aspx?Id=VMCollectionWrapperSynchronizeaModelcollectionwithaViewModelcollection

https://blog.notifychanged.com/2009/01/30/viewmodelling-lists/

Which code appears to be based off another interesting beast, multithreaded collection for WPF(?!)

https://lambert.geek.nz/2007/10/30/wpf-multithreaded-collections/

which page refers to another similar beast… well actually it diverges somewhat from the keeping collections synchronized, and gets into thread-safety stuff now, but I still find it interesting tracing the sort of genealogies that occur here, and seeing the way knowledge spreads across the internet.

Of course stackoverflow hasn’t missed this question either:

https://stackoverflow.com/questions/2426268/synchronizing-a-collection-of-wrapped-objects-with-a-collection-of-unwrapped-obje

https://stackoverflow.com/questions/1256793/mvvm-sync-collections

 

Useless trivia: at some point I stumble on another curious dinosaur I have never seen before, BindingList<T>.

“Provides a generic collection that supports data binding.”

Huh? Sometimes MSDN’s descriptions leave me feeling a little sad. Reading further on the interwebs, apparently BindingList<T> predates WPF, and is not related to the problem at all. Oh well.