有关在MvvmCross中何时何地使用ObservableCollection的建议 [英] Advice on where and when to use ObservableCollection in MvvmCross

查看:70
本文介绍了有关在MvvmCross中何时何地使用ObservableCollection的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在MvvmCross解决方案中,我有一个单例服务类,该类从Web服务获取项目并更新公共的ObservableCollection.它每五秒钟执行一次,并且可能会添加或删除项或更改其属性.

我还有一个ViewModel,它具有一个设置为服务的ObservableCollection的公共属性.视图绑定到ObservableCollection,以便在添加,删除或更改项目时,视图应更新以显示该视图.

但是,正如预期的那样,我收到一个线程异常,因为ObservableCollection是由Main/UI以外的线程更新的,因此绑定无法更新UI.

在Service内,我没有随时可用的InvokeOnMainThread调用,因此在更新ObservableCollection时没有明显的跨平台方法可返回到主线程.另外,这样做似乎是错误的-服务不应该将自己与UI事务相关(而ViewModel可以).

另外,对于从服务中公开事件,如果这会导致ViewModels不被垃圾收集,我也感到有些紧张.我注意到,在@slodge的N + 1系列 http://mvvmcross.wordpress.com/中,他正在使用信使服务大概就是为了避免这种情况.

因此,一种可能的解决方案可能是发布一条包含最新项列表的消息,然后让ViewModel订阅该消息,并通过将消息内容与其进行比较来在UI线程上更新其自己的ObservableCollection.但这似乎有些笨拙.

对于实现此最佳方法的任何建议,我们将不胜感激-谢谢.

解决方案

最初必须在UI线程上调用INotifyCollectionChanged的原始要求实际上来自Windows控件根据添加/删除/移动"更新的同步方式. /已替换/重置通知.

当然,这种同步更新是完全明智的-当另一个线程正在主动更改UI显示时,很难更新它.

.Net 4.5中有新"更改,这可能意味着未来会更好……但是总体而言,这些对我来说看起来相当复杂-请参见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.

解决方案

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:

  • the frequency, type and size of the collection changes - e.g. whether you are only getting occasional single line updates, whether you are getting frequent large bursts of changes, or whether you are mainly seeing complex groups of changes (which essentially are Resets as far as the UI is concerned)
  • the animation level required in the UI - e.g. should added/deleted items animate in/out? If no animation is required then it can sometimes be easier just to replace the entire list with a new snapshot rather than to work out the incremental changes.
  • the size of the collection itself - obviously duplicating a large collection can cause out-of-memory issues
  • the persistence required on the collection - if persistence is required, then 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?

这篇关于有关在MvvmCross中何时何地使用ObservableCollection的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆