关于在MvvmCross中何时何地使用ObservableCollection的建议

关于在MvvmCross中何时何地使用ObservableCollection的建议,mvvm,windows-phone-8,xamarin.ios,mvvmcross,Mvvm,Windows Phone 8,Xamarin.ios,Mvvmcross,在MvvmCross解决方案中,我有一个singleton服务类,它从web服务获取项目并更新公共ObservableCollection。它每五秒钟执行一次,可以添加或删除项目或更改其属性 我还有一个ViewModel,它有一个公共属性,设置为服务的ObservableCollection。视图绑定到ObservableCollection,因此当添加、删除或更改项时,视图应该更新以显示这一点 但是,正如预期的那样,我得到了一个线程异常,因为ObservableCollection正在由一个线

在MvvmCross解决方案中,我有一个singleton服务类,它从web服务获取项目并更新公共ObservableCollection。它每五秒钟执行一次,可以添加或删除项目或更改其属性

我还有一个ViewModel,它有一个公共属性,设置为服务的ObservableCollection。视图绑定到ObservableCollection,因此当添加、删除或更改项时,视图应该更新以显示这一点

但是,正如预期的那样,我得到了一个线程异常,因为ObservableCollection正在由一个线程而不是Main/UI线程更新,因此绑定无法更新UI

在服务中,我没有现成的
InvokeOnMainThread
调用,因此在更新ObservableCollection时,没有明显的跨平台方法返回到主线程。而且,这样做似乎是错误的——服务不应该关心UI问题(而ViewModel可以)

另外,我有点担心从服务中暴露事件,以防这导致ViewModels不能被垃圾收集。我注意到在@slodge的N+1系列中,他使用消息传送服务大概是为了避免这种情况

因此,一个可能的解决方案可能是发布一条包含最新项目列表的消息,ViewModel订阅该消息,并通过将消息内容与之进行比较,在UI线程上更新其自己的ObservableCollection。但这似乎有点笨重


如果您对实现此功能的最佳方式有任何建议,我们将不胜感激。

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

当然,这种同步更新是完全合理的——当另一个线程正在积极更改UI显示时,更新UI显示将非常困难

在.NET4.5中有一些“新”的变化,这可能意味着未来会更好。。。但总的来说,这些看起来相当复杂-看到了吗


我所知道的处理这些问题的方法基本上与您的帖子中所述的方法相同:

A.将
ObservableCollection
保留在服务/模型层,并将其中的所有事件封送到UI线程上-这可以使用从
MvxMainThreadDispatchingObject
继承的任何类,也可以通过调用
MvxMainThreadDispatcher.Instance.RequestMainThreadAction(action)

不幸的是,这意味着您的服务/模型确实具备一些线程知识,但这种方法可以很好地用于整体应用程序体验

B.在
ViewModel
中复制集合-通过一些弱引用类型机制进行更新

  • e、 g.通过向it部门发送消息,告知其添加、删除、替换或移动了哪些内容(或完全重置)-请注意,要使其正常工作,则消息必须以正确的顺序到达

  • 或者,允许从服务/模型层发送快照

选择哪一项取决于:

  • 集合更改的频率、类型和大小-例如,您是否仅获得偶尔的单行更新,您是否获得频繁的大批量更改,或者您是否主要看到复杂的更改组(就UI而言,基本上是重置)
  • UI中所需的动画级别-例如,添加/删除的项目是否应在输入/输出中设置动画?如果不需要动画,那么用一个新快照替换整个列表有时会比计算增量更改更容易
  • 集合本身的大小-显然,复制大型集合可能会导致内存不足问题
  • 集合上需要的持久性-如果需要持久性,则
    ObservableCollection
    本身可能不合适,您可能需要使用自定义
    INotifyCollectionChanged
    实现(如)
我个人通常在应用程序中选择(A)方法,但这取决于情况、集合的特征及其变化


请注意,虽然这绝对是一个
mvvm
问题,潜在的问题是一个独立于数据绑定的问题-当列表本身在后台线程上更改时,如何更新列表的屏幕显示?

新的
EnableCollectionsSynchronization
看起来很有趣,但你是对的-它看起来很复杂,必须实现锁定与编组事件一样麻烦。好的,看来A毕竟是可行的,我猜如果ViewModel没有处理它的任何事件,那么它就不会通过从服务引用而保持活动状态。因此,再次感谢您提供了全面的答案和如何从服务返回主线程的提示。我尝试了这个
MvxMainThreadDispatcher.Instance.RequestMainThreadAction
,但没有任何帮助:(还能做什么?全部问题