void sectionCollectionChanged(int section, IList <NotifyCollectionChangedEventArgs> xs) { if (xs.Count == 0) { return; } var resetOnlyNotification = new [] { new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset) }; this.Log().Info("Changed contents: [{0}]", String.Join(",", xs.Select(x => x.Action.ToString()))); if (xs.Any(x => x.Action == NotifyCollectionChangedAction.Reset)) { this.Log().Info("About to call ReloadData"); adapter.ReloadData(); didPerformUpdates.OnNext(resetOnlyNotification); return; } var updates = xs.Select(ea => Tuple.Create(ea, getChangedIndexes(ea))).ToList(); var allChangedIndexes = updates.SelectMany(u => u.Item2).ToList(); // Detect if we're changing the same cell more than // once - if so, issue a reset and be done if (allChangedIndexes.Count != allChangedIndexes.Distinct().Count()) { this.Log().Info("Detected a dupe in the changelist. Issuing Reset"); adapter.ReloadData(); didPerformUpdates.OnNext(resetOnlyNotification); return; } this.Log().Info("Beginning update"); adapter.PerformBatchUpdates(() => { foreach (var update in updates.AsEnumerable().Reverse()) { var changeAction = update.Item1.Action; var changedIndexes = update.Item2; switch (changeAction) { case NotifyCollectionChangedAction.Add: doUpdate(adapter.InsertItems, changedIndexes, section); break; case NotifyCollectionChangedAction.Remove: doUpdate(adapter.DeleteItems, changedIndexes, section); break; case NotifyCollectionChangedAction.Replace: doUpdate(adapter.ReloadItems, changedIndexes, section); break; case NotifyCollectionChangedAction.Move: // NB: ReactiveList currently only supports single-item // moves var ea = update.Item1; this.Log().Info("Calling MoveRow: {0}-{1} => {0}{2}", section, ea.OldStartingIndex, ea.NewStartingIndex); adapter.MoveItem( NSIndexPath.FromRowSection(ea.OldStartingIndex, section), NSIndexPath.FromRowSection(ea.NewStartingIndex, section)); break; default: this.Log().Info("Unknown Action: {0}", changeAction); break; } } this.Log().Info("Ending update"); didPerformUpdates.OnNext(xs); }); }
public CommonReactiveSource( IUICollViewAdapter <TUIView, TUIViewCell> adapter, IEnumerable <ISectionInformation <TUIView, TUIViewCell> > sectionInfo) { this.adapter = adapter; this.sectionInfo = sectionInfo.ToList(); for (int i = 0; i < this.sectionInfo.Count; i++) { var current = this.sectionInfo[i].Collection; var section = i; var disp = current.Changed.Buffer(TimeSpan.FromMilliseconds(250), RxApp.MainThreadScheduler).Subscribe(xs => { if (xs.Count == 0) { return; } var resetOnlyNotification = new [] { new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset) }; this.Log().Info("Changed contents: [{0}]", String.Join(",", xs.Select(x => x.Action.ToString()))); if (xs.Any(x => x.Action == NotifyCollectionChangedAction.Reset)) { this.Log().Info("About to call ReloadData"); adapter.ReloadData(); didPerformUpdates.OnNext(resetOnlyNotification); return; } var updates = xs.Select(ea => Tuple.Create(ea, getChangedIndexes(ea))).ToList(); var allChangedIndexes = updates.SelectMany(u => u.Item2).ToList(); // Detect if we're changing the same cell more than // once - if so, issue a reset and be done if (allChangedIndexes.Count != allChangedIndexes.Distinct().Count()) { this.Log().Info("Detected a dupe in the changelist. Issuing Reset"); adapter.ReloadData(); didPerformUpdates.OnNext(resetOnlyNotification); return; } this.Log().Info("Beginning update"); adapter.PerformBatchUpdates(() => { foreach (var update in updates.AsEnumerable().Reverse()) { var changeAction = update.Item1.Action; var changedIndexes = update.Item2; switch (changeAction) { case NotifyCollectionChangedAction.Add: doUpdate(adapter.InsertItems, changedIndexes, section); break; case NotifyCollectionChangedAction.Remove: doUpdate(adapter.DeleteItems, changedIndexes, section); break; case NotifyCollectionChangedAction.Replace: doUpdate(adapter.ReloadItems, changedIndexes, section); break; case NotifyCollectionChangedAction.Move: // NB: ReactiveList currently only supports single-item // moves var ea = update.Item1; this.Log().Info("Calling MoveRow: {0}-{1} => {0}{2}", section, ea.OldStartingIndex, ea.NewStartingIndex); adapter.MoveItem( NSIndexPath.FromRowSection(ea.OldStartingIndex, section), NSIndexPath.FromRowSection(ea.NewStartingIndex, section)); break; default: this.Log().Info("Unknown Action: {0}", changeAction); break; } } this.Log().Info("Ending update"); didPerformUpdates.OnNext(xs); }); }); innerDisp.Add(disp); } }