/// <summary> /// Binds a clone of the observable changeset to the target <see cref="IObservableDynamicDataRangeCollection"/> /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source">The source.</param> /// <param name="targetCollection">The target collection.</param> /// <param name="resetThreshold">The reset threshold.</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException"> /// source or targetCollection /// </exception> public static IObservable <IChangeSet <T> > Bind <T>([NotNull] this IObservable <IChangeSet <T> > source, [NotNull] IObservableDynamicDataRangeCollection <T> targetCollection, int resetThreshold = 25) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (targetCollection == null) { throw new ArgumentNullException(nameof(targetCollection)); } var adaptor = new ObservableListToObservableDynamicDataRangeCollectionAdapter <T>(targetCollection, resetThreshold); return(source.Adapt(adaptor)); }
internal static void CloneObservableDynamicDataRangeCollection <T>(this IObservableDynamicDataRangeCollection <T> source, IChangeSet <T> changes) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (changes == null) { throw new ArgumentNullException(nameof(changes)); } var i = 0; foreach (var item in changes) { switch (item.Reason) { case ListChangeReason.Add: { var change = item.Item; var hasIndex = change.CurrentIndex >= 0; if (hasIndex) { source.Insert(change.CurrentIndex, change.Current); } else { source.Add(change.Current); } break; } case ListChangeReason.AddRange: { var previousChange = changes.ElementAtOrDefault(i - 1); if (previousChange != null && previousChange.Reason == ListChangeReason.Clear) { source.ReplaceRange(item.Range); } else { source.AddOrInsertRange(item.Range, item.Range.Index); } break; } case ListChangeReason.Clear: { var nextChange = changes.ElementAtOrDefault(i + 1); if (nextChange != null && nextChange.Reason != ListChangeReason.AddRange) { source.Clear(); } break; } case ListChangeReason.Replace: { var change = item.Item; bool hasIndex = change.CurrentIndex >= 0; if (hasIndex && change.CurrentIndex == change.PreviousIndex) { source[change.CurrentIndex] = change.Current; } else { source.RemoveAt(change.PreviousIndex); source.Insert(change.CurrentIndex, change.Current); } break; } case ListChangeReason.Remove: { var change = item.Item; bool hasIndex = change.CurrentIndex >= 0; if (hasIndex) { source.RemoveAt(change.CurrentIndex); } else { source.Remove(change.Current); } break; } case ListChangeReason.RemoveRange: { source.RemoveRange(item.Range); break; } case ListChangeReason.Moved: { var change = item.Item; bool hasIndex = change.CurrentIndex >= 0; if (!hasIndex) { throw new UnspecifiedIndexException("Cannot move as an index was not specified"); } source.Move(change.PreviousIndex, change.CurrentIndex); break; } } i++; } }
/// <summary> /// Initializes a new instance of the <see cref="ObservableListToObservableDynamicDataRangeCollectionAdapter{TObject,TKey}"/> class. /// </summary> /// <param name="target">The target.</param> /// <param name="resetThreshold">The reset threshold.</param> /// <exception cref="System.ArgumentNullException">target</exception> public ObservableListToObservableDynamicDataRangeCollectionAdapter(IObservableDynamicDataRangeCollection <TObject> target, int resetThreshold = 50) { _target = target ?? throw new ArgumentNullException(nameof(target)); _resetThreshold = resetThreshold; }