ViewModel paging & BindingCollection questions

Jul 27, 2010 at 9:51 AM

Firstly Rob,

Many thanks for all the hard work you have invested in Caliburn, us lesser mortals are very appreciative of your efforts.

I have been experimenting with MVVM in my homebrew application (media archiving application), and up until spending some time with Caliburn Micro I haven't really put in the time and effort to invest in refactoring my application to use any of the MVVM frameworks out there; I suppose you could say I have 'rolled my own' very light MVVM approach that has little bits of various blogs and tricks I've found on the Web (props to Josh Smith, Sacha Barber & Bill Kempf for some of these)

However, Caliburn is the 1st that really makes me want to put in that effort - mostly due to the convention based approach coupled with ActionMessages (RelayCommand gives me almost enough currently, but I want to make this app in Silverlight too)

Anyway, I have been playing with Micro over the past week, and gradually easing it into my application, in a very piecemeal approach, starting with the bootstrapper.

I've now been looking at probably the biggest part of adopting Caliburn Micro - which is replacing my own ViewModelBase implementation with Caliburn, and before I go much further there are a couple of things I'd like to clarify and get some guidance on how these thinsg are handled with Caliburn:-

1. Paging - my application uses extensive server-side paging, and I've put together a PagedViewModel<T> generic base class that handles all the paging across all my media types(Movie, Album, TV Series etc, etc). I'm quite pleased with this useful ViewModel - it abstracts away all the issues of paging in the ViewModel and so far I've yet to see any MVVM framework that provides a 'boilerplate' ViewModel that supports paging - how do you deal with this using Caliburn? I'm more than happy to pass on my code if you think it would be useful in assisting.

2. ObservableCollection extensions - I'm currently using a variation of Dean Chalk's thread-safe/dispatcher aware ObservableCollection :- http://www.deanchalk.me.uk/post/Thread-Safe-Dispatcher-Safe-Observable-Collection-for-WPF.aspx, and I had hoped to simply substitute in BindableCollection<T> from Caliburn, but when I tried it reverts back to the old ("This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread" exception on the page.Clear method - even ClearItems does not Execute on the UI thread currently) - I'm guessing that this was by design to keep Caliburn.Micro lean and mean, but it's a shame that this collection has to be overridden to be useful; in my current implementation it's not really a 'bindable' collection.

Anyway, other than these two issues, I'm really liking the framework - lots of great stuff.

Cheers


Ritchie

 

 

 

Jul 27, 2010 at 11:01 AM
Edited Jul 27, 2010 at 11:02 AM

Regarding the second issue, are you using the trunk version of Caliburn.Micro? A patch has been applyed to the previous version of BindableCollection<T>, and now it acts more or less like Dean Chalk's implementation, since both modification and notification are dispatched to the UI thread if needed.

The missing part is synchronization, which it's not needed, in my opinion. The main reasons I think this way are:

1. Synchronization between worker thread an UI thread is accomplished by dispatching modifications to the UI thread (since the collection is modified on the Dispatcher and the notification are dispatched too, there is no way that the dispatcher access to the collection while it is being modified...)

2. If synchronization is really needed (i.e. performing a long asynchronous operation on the collection, while keeping possible collection modification), it should be properly implemented on the ViewModel class, and not embedded in the collection, which is agnostic regarding the usage of the collection itself. Moreover, the implementation you are using has an awful drawback: it is not thread-safe on enumeration (a worker thread could enumerate the collection while the UI thread is handling the dispatched modification, causing an exception).

Regarding the synchronization part, I wrote down a completely thread-safe collection, that synchronizes modification and enumeration, exposes the synchronization object publicly so that it is possible to extend synchronization capabilities (something like lock the collection while checking if an element is already present before adding it) and, finally, can act as a wrapper on an existing collection, or can be used as a back-end for an observable collection. As you can imagine, it is quite a handy collection. Nevertheless I prefer to avoid using it on ViewModel/View implementations, keeping it in my Model implementation and using it wisely, since a lot of problems can occur (i.e. Linq extensions metod for collections are of not thread safe, unless they are wrapped in proper synchronization code; introducing synchronization on the UI thread can cause hard to find deadlocks, and event compromise UI responsiveness; a self-synchronized implementation is not really a thread-safe implementation, since it does not take into account how the collection is used... that's why .NET do not provide anymore self-synchonizing collections).

If Rob is interested, I can send him the code for such collection, so that he can inspect it and decide if it is worth to be added to the Caliburn.Micro framework... but again, such implementations are not suited for the ViewModel/View side.

Jul 27, 2010 at 11:10 AM
Edited Jul 27, 2010 at 11:12 AM

Blade, thanks for the pointer, I will have a look at trunk.

As far as synchronisation goes, I wasn't really wanting the thread-safe part of Dean's implementation in any event, I agree that any synchronisation should be handled by the owner of the collection; i.e. the ViewModel.

 

Do you have any insights on Paging in MVVM; i.e. have you seen anything similar in any other frameworks to what I am referring in point 1? I find it very useful, but I'd really like to compare my implementation against other solutions.

Cheers

 

 

 

Jul 27, 2010 at 11:27 AM
Being primary a Client-side developer, I have never dealt with server-side paging issues... thanks God! :)
Jul 27, 2010 at 12:31 PM
BladeWise wrote:
Being primary a Client-side developer, I have never dealt with server-side paging issues... thanks God! :)

 That's one of the reasons I like MVVM and Caliburn in particular - I'm next to useless with UI's (my day-job is more integration and server-side WCF services!), so anything that allows me to do a crap-looking but functional View, that can then be passed to someone who can make it look nice in Blend without breaking the functionality is going to be right up my street.

 

 

Coordinator
Jul 27, 2010 at 2:31 PM

@BladeWise Thanks for offering the sync safe collection. I think I'll hold off for the moment on adding something like that. Some of the bug fixes and minor improvements have grown the framework recently, so I have to be very choosey now with what I put in. Something like that can be easily added from the outside without affecting internal framework workings. I'm thinking of creating a "recipes" section of the project. So, that might be a good snippet to put there when it is ready.

@ritchiebox I've built pagination VMs in the past. But, I haven't been completely satisfied that my implementation was sufficiently generalized or high enough quality to put into the framework. If I were to build one on CM, I would probably think about using Conductor<T>.Collection.OneActive as a base class. You might want to take a look at it, though I can't be sure that it is definitely the right starting point. If you do build a pagination model on top of any CM infrastructure, I think that would make an excellent contribution to a "recipes" section and I'd love to study it.

Jul 27, 2010 at 2:41 PM

Thanks for that Rob, it gives me something to look into.