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
The original requirement that INotifyCollectionChanged
must be called on the UI thread really comes from the synchronous way that the Windows controls update based upon the Added/Removed/Moved/Replaced/Reset notifications.
This synchronous update is, of course, entirely sensible - it would be very hard to update the UI display while another thread is actively changing it.
There are 'new' changes in .Net 4.5 which may mean the future is nicer... but overall these look quite complicated to me - see https://stackoverflow.com/a/14602121/373321
The ways I know of to handle this are essentially the same as those outlined in your post:
A. keep the ObservableCollection
in the Service/Model layer and marshal all events there onto the UI thread - this is possible using any class which inherits from MvxMainThreadDispatchingObject
- or can be done by calling MvxMainThreadDispatcher.Instance.RequestMainThreadAction(action)
Whilst it's unfortunate that this means your Service/Model does have some threading knowledge, this approach can work well for the overall App experience.
B. make a duplicate copy of the collection in the ViewModel
- updating it by some weak reference type mechanism
e.g. by sending it Messages which tell it what has been Added, Removed, Replaced or Moved (or completely Reset) - note that for this to work, then it's important that the Messages arrive in the correct order!
or e.g. allowing snapshots to be sent across from the Service/Model layer
Which of these to choose depends on:
Resets
as far as the UI is concerned)ObservableCollection
itself may not be appropriate and you may need to use a custom INotifyCollectionChanged
implementation (like the MyCustomList samples)I personally generally choose the (A) approach in apps - but it does depend on the situation and on the characteristics of the collection and its changes.
Note that while this is most definitely an mvvm
issue, the underlying problem is one independent of databinding - how do you update an on-screen display of a list while the list itself is changing on a background thread?