private IVirtualChangeSet <TObject, TKey> Virtualise(ISortedChangeSet <TObject, TKey> updates = null) { if (_isLoaded == false) { return(null); } var previous = _current; var virualised = _all.Skip(_parameters.StartIndex) .Take(_parameters.Size) .ToList(); _current = new KeyValueCollection <TObject, TKey>(virualised, _all.Comparer, updates?.SortedItems.SortReason ?? SortReason.DataChanged, _all.Optimisations); ////check for changes within the current virtualised page. Notify if there have been changes or if the overall count has changed var notifications = _changedCalculator.Calculate(_current, previous, updates); if (notifications.Count == 0 && (previous.Count != _current.Count)) { return(null); } var response = new VirtualResponse(_parameters.Size, _parameters.StartIndex, _all.Count); return(new VirtualChangeSet <TObject, TKey>(notifications, _current, response)); }
private void DoUpdate(ISortedChangeSet <TObject, TKey> updates, IObservableCollection <TObject> list) { updates.ForEach(update => { switch (update.Reason) { case ChangeReason.Add: list.Insert(update.CurrentIndex, update.Current); break; case ChangeReason.Remove: list.RemoveAt(update.CurrentIndex); break; case ChangeReason.Moved: list.Move(update.PreviousIndex, update.CurrentIndex); break; case ChangeReason.Update: { list.RemoveAt(update.PreviousIndex); list.Insert(update.CurrentIndex, update.Current); } break; } }); }
/// <summary> /// Maintains the specified collection from the changes /// </summary> /// <param name="changes">The changes.</param> /// <param name="collection">The collection.</param> public void Adapt(ISortedChangeSet <TObject, TKey> changes, IObservableCollection <TObject> collection) { switch (changes.SortedItems.SortReason) { case SortReason.InitialLoad: { if (changes.Count > _refreshThreshold()) { using (collection.SuspendNotifications()) { collection.Load(changes.SortedItems.Select(kv => kv.Value)); } } else { using (collection.SuspendCount()) { DoUpdate(changes, collection); } } } break; case SortReason.ComparerChanged: case SortReason.Reset: using (collection.SuspendNotifications()) { collection.Load(changes.SortedItems.Select(kv => kv.Value)); } break; case SortReason.DataChanged: if (changes.Count > _refreshThreshold()) { using (collection.SuspendNotifications()) { collection.Load(changes.SortedItems.Select(kv => kv.Value)); } } else { using (collection.SuspendCount()) { DoUpdate(changes, collection); } } break; case SortReason.Reorder: //Updates will only be moves, so appply logic using (collection.SuspendCount()) { DoUpdate(changes, collection); } break; default: throw new ArgumentOutOfRangeException(); } }
private void DoUpdate(ISortedChangeSet <TObject, TKey> changes) { foreach (var change in changes) { switch (change.Reason) { case ChangeReason.Add: _list.Insert(change.CurrentIndex, change.Current); break; case ChangeReason.Remove: _list.RemoveAt(change.CurrentIndex); break; case ChangeReason.Moved: _list.RemoveAt(change.PreviousIndex); _list.Insert(change.CurrentIndex, change.Current); break; case ChangeReason.Update: _list.RemoveAt(change.PreviousIndex); _list.Insert(change.CurrentIndex, change.Current); break; } } }
private IPagedChangeSet <TObject, TKey>?Paginate(ISortedChangeSet <TObject, TKey>?updates = null) { if (_isLoaded == false) { return(null); } var previous = _current; int pages = CalculatePages(); int page = _request.Page > pages ? pages : _request.Page; int skip = _request.Size * (page - 1); var paged = _all.Skip(skip).Take(_request.Size).ToList(); _current = new KeyValueCollection <TObject, TKey>(paged, _all.Comparer, updates?.SortedItems.SortReason ?? SortReason.DataChanged, _all.Optimisations); // check for changes within the current virtualised page. Notify if there have been changes or if the overall count has changed var notifications = FilteredIndexCalculator <TObject, TKey> .Calculate(_current, previous, updates); if (notifications.Count == 0 && (previous.Count != _current.Count)) { return(null); } var response = new PageResponse(_request.Size, _all.Count, page, pages); return(new PagedChangeSet <TObject, TKey>(_current, notifications, response)); }
private void DoUpdate(ISortedChangeSet <TObject, TKey> updates, IObservableCollection <TObject> list) { foreach (var update in updates) { switch (update.Reason) { case ChangeReason.Add: list.Insert(update.CurrentIndex, update.Current); break; case ChangeReason.Remove: list.RemoveAt(update.CurrentIndex); break; case ChangeReason.Moved: list.Move(update.PreviousIndex, update.CurrentIndex); break; case ChangeReason.Update: if (update.PreviousIndex != update.CurrentIndex) { list.RemoveAt(update.PreviousIndex); list.Insert(update.CurrentIndex, update.Current); } else { list.Replace(update.Previous.Value, update.Current); } break; } } }
/// <inheritdoc /> public void Adapt(ISortedChangeSet <TObject, TKey> changes) { if (changes == null) { throw new ArgumentNullException(nameof(changes)); } switch (changes.SortedItems.SortReason) { case SortReason.InitialLoad: case SortReason.ComparerChanged: case SortReason.Reset: using (new BindingListEventsSuspender <TObject>(_list)) { _list.Clear(); _list.AddRange(changes.SortedItems.Select(kv => kv.Value)); } break; case SortReason.DataChanged: if (changes.Count - changes.Refreshes > _refreshThreshold) { using (new BindingListEventsSuspender <TObject>(_list)) { _list.Clear(); _list.AddRange(changes.SortedItems.Select(kv => kv.Value)); } } else { DoUpdate(changes); } break; case SortReason.Reorder: DoUpdate(changes); break; default: throw new ArgumentOutOfRangeException(nameof(changes)); } }
/// <summary> /// Adapts the specified sorted changeset /// </summary> /// <param name="changes">The changes.</param> public void Adapt(ISortedChangeSet <TObject, TKey> changes) { switch (changes.SortedItems.SortReason) { case SortReason.InitialLoad: case SortReason.ComparerChanged: case SortReason.Reset: { using (_target.SuppressChangeNotifications()) { _target.Clear(); _target.AddRange(changes.SortedItems.Select(kv => kv.Value)); } } break; case SortReason.DataChanged: { if (changes.Count > _resetThreshold) { using (_target.SuppressChangeNotifications()) { _target.Clear(); _target.AddRange(changes.SortedItems.Select(kv => kv.Value)); } } else { DoUpdate(changes); } } break; case SortReason.Reorder: //Updates will only be moves, so appply logic DoUpdate(changes); break; default: throw new ArgumentOutOfRangeException(); } }
public void TreatMovesAsRemoveAdd() { var cache = new SourceCache <Person, string>(p => p.Name); var people = Enumerable.Range(0, 10).Select(age => new Person("Person" + age, age)).ToList(); var importantGuy = people.First(); cache.AddOrUpdate(people); ISortedChangeSet <Person, string> latestSetWithoutMoves = null; ISortedChangeSet <Person, string> latestSetWithMoves = null; var boundList1 = new ReactiveList <Person>(); var boundList2 = new ReactiveList <Person>(); using (cache.Connect() .AutoRefresh(p => p.Age) .Sort(SortExpressionComparer <Person> .Ascending(p => p.Age)) .TreatMovesAsRemoveAdd() .Bind(boundList1) .Subscribe(set => latestSetWithoutMoves = set)) using (cache.Connect() .AutoRefresh(p => p.Age) .Sort(SortExpressionComparer <Person> .Ascending(p => p.Age)) .Bind(boundList2) .Subscribe(set => latestSetWithMoves = set)) { importantGuy.Age = importantGuy.Age + 200; latestSetWithoutMoves.Removes.Should().Be(1); latestSetWithoutMoves.Adds.Should().Be(1); latestSetWithoutMoves.Moves.Should().Be(0); latestSetWithoutMoves.Updates.Should().Be(0); latestSetWithMoves.Moves.Should().Be(1); latestSetWithMoves.Updates.Should().Be(0); latestSetWithMoves.Removes.Should().Be(0); latestSetWithMoves.Adds.Should().Be(0); } }
public void TreatMovesAsRemoveAdd() { var cache = new SourceCache <Person, string>(p => p.Name); var people = Enumerable.Range(0, 10).Select(age => new Person("Person" + age, age)).ToList(); var importantGuy = people.First(); cache.AddOrUpdate(people); ISortedChangeSet <Person, string>?latestSetWithoutMoves = null; ISortedChangeSet <Person, string>?latestSetWithMoves = null; var boundList1 = new ObservableCollectionExtended <Person>(); var boundList2 = new ObservableCollectionExtended <Person>(); using (cache.Connect().AutoRefresh(p => p.Age).Sort(SortExpressionComparer <Person> .Ascending(p => p.Age)).TreatMovesAsRemoveAdd().Bind(boundList1).Subscribe(set => latestSetWithoutMoves = set)) using (cache.Connect().AutoRefresh(p => p.Age).Sort(SortExpressionComparer <Person> .Ascending(p => p.Age)).Bind(boundList2).Subscribe(set => latestSetWithMoves = set)) { if (latestSetWithoutMoves is null) { throw new InvalidOperationException(nameof(latestSetWithoutMoves)); } if (latestSetWithMoves is null) { throw new InvalidOperationException(nameof(latestSetWithMoves)); } importantGuy.Age += 200; latestSetWithoutMoves.Should().NotBeNull(); latestSetWithoutMoves.Removes.Should().Be(1); latestSetWithoutMoves.Adds.Should().Be(1); latestSetWithoutMoves.Moves.Should().Be(0); latestSetWithoutMoves.Updates.Should().Be(0); latestSetWithMoves.Moves.Should().Be(1); latestSetWithMoves.Updates.Should().Be(0); latestSetWithMoves.Removes.Should().Be(0); latestSetWithMoves.Adds.Should().Be(0); } }
public IVirtualChangeSet <TObject, TKey> Update(ISortedChangeSet <TObject, TKey> updates) { _isLoaded = true; _all = updates.SortedItems; return(Virtualise(updates)); }
public IPagedChangeSet <TObject, TKey>?Update(ISortedChangeSet <TObject, TKey> updates) { _isLoaded = true; _all = updates.SortedItems; return(Paginate(updates)); }