In an MvvmCross solution I have a singleton Service class which gets items from a web service and updates a public ObservableCollection. It does this every five seconds and items may be added or removed or their properties changed.
I also have a ViewModel which has a public property which is set to the Service's ObservableCollection. The View is bound to the ObservableCollection so that when items are added, removed or changed the view should update to show this.
However, as expected, I am getting a threading exception because the ObservableCollection is being updated by a thread other than the Main/UI one and the binding therefore cannot update the UI.
Within the Service I do not have the InvokeOnMainThread
call readily available so there is no obvious cross platform way to get back on to the main thread when updating the ObservableCollection. Also, doing this just seems wrong - a Service shouldn't be concerning itself with UI matters (whereas a ViewModel can).
Also I am a bit nervous about exposing events from a Service in case this causes ViewModels to not be Garbage Collected. I note that in @slodge's N+1 series http://mvvmcross.wordpress.com/ he is using a messenging service presumably to avoid just this.
So a possible solution may be to publish a message with the latest list of items, and for the ViewModel to subscribe to the message and update its own ObservableCollection on the UI thread by comparing the message contents to it. But this seems a little clunky.
Any suggestions on the best way to implement this would be appreciated - thanks.
EnableCollectionSynchronization
looks interesting but you're right - it does look complicated, having to implement the locking is as much trouble as marshalling the events. Okay, so it looks like A IS doable after all and I guess if the ViewModel isn't handling any of its events then it won't be kept alive by being referenced from the Service. So, thanks again for a thorough answer and the tips on how to get back onto the Main thread from the Service. – Lipo