以前WPFにバインディングされたObservableCollectionを他スレッドから操作すると例外になる 件で悩んだ以後、CollectionのAdd/Removeはせずに毎回Collectionを作り直すという消極策に出ていたのですが、今回どうやら避けて通れない事態に。View側でCollectionChangedイベント監視するの面倒だなぁと思ってたら、答え は意外にも簡単なところに。去年もうちょっとちゃんと調べればよかった。
なんとなくViewModel/ModelがViewの事情に譲歩しているような気もしますが、これくらいなら個人的には許容範囲。(UIスレッドのDispatcher得るためにViewとViewModelに細工しないといけないならやるか悩んだかも)
[2018/4/23 追記] .NET Framework 4.5以上ではBindingOperations.EnableCollectionSynchronization を使ったほうが楽でしょう。私も場合、いまだにXPで動いている案件が有ったりするので…
using System.Collections.ObjectModel; using System.Windows.Threading; class DispatchedCollection<T> : ObservableCollection<T> { Dispatcher uiDispatcher = System.Windows.Application.Current.Dispatcher; protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (uiDispatcher.CheckAccess()) { base.OnCollectionChanged(e); } else { uiDispatcher.Invoke(new Action(() => base.OnCollectionChanged(e))); } } }
Comments