예제 #1
0
        private void Update(Chunk <NotifyCollectionChangedEventArgs> changes)
        {
            if (changes == null || changes.Count == 0)
            {
                return;
            }

            using (changes.ClearTransaction())
            {
                if (changes.Count > 1)
                {
                    this.Refresh(changes);
                    return;
                }

                var e = changes[0];
                switch (e.Action)
                {
                case NotifyCollectionChangedAction.Add:
                {
                    if (!e.TryGetSingleNewItem(out TSource newSource))
                    {
                        goto case NotifyCollectionChangedAction.Reset;
                    }

                    var index = e.NewStartingIndex;
                    var value = this.GetOrCreate(newSource, index);
                    this.Tracker.Insert(index, value);
                    var args = this.UpdateRange(index + 1, this.Count - 1);
                    args.Add(Diff.CreateAddEventArgs(value, index));
                    this.Notify(args);
                    break;
                }

                case NotifyCollectionChangedAction.Remove:
                {
                    if (!e.TryGetSingleOldItem(out TSource oldSource))
                    {
                        goto case NotifyCollectionChangedAction.Reset;
                    }

                    var index = e.OldStartingIndex;
                    var value = this.Tracker[index];
                    this.Tracker.RemoveAt(index);
                    var argses = this.UpdateRange(index, this.Count - 1);
                    argses.Add(Diff.CreateRemoveEventArgs(value, index));
                    this.Notify(argses);
                    this.factory.Remove(oldSource, value);
                    break;
                }

                case NotifyCollectionChangedAction.Replace:
                {
                    if (!e.TryGetSingleNewItem(out TSource newSource) ||
                        !e.TryGetSingleOldItem(out TSource oldSource))
                    {
                        goto case NotifyCollectionChangedAction.Reset;
                    }

                    var index    = e.NewStartingIndex;
                    var value    = this.GetOrCreate(newSource, index);
                    var oldValue = this.Tracker[e.OldStartingIndex];
                    this.Tracker[index] = value;
                    var arg = Diff.CreateReplaceEventArgs(value, oldValue, index);
                    this.Notify(arg);
                    this.factory.Remove(oldSource, oldValue);
                    break;
                }

                case NotifyCollectionChangedAction.Move:
                {
                    var value = this.Tracker[e.OldStartingIndex];
                    this.Tracker.RemoveAt(e.OldStartingIndex);
                    this.Tracker.Insert(e.NewStartingIndex, value);
                    var args = this.UpdateRange(Math.Min(e.OldStartingIndex, e.NewStartingIndex), Math.Max(e.OldStartingIndex, e.NewStartingIndex));
                    args.Add(Diff.CreateMoveEventArgs(value, e.NewStartingIndex, e.OldStartingIndex));
                    this.Notify(args);
                    break;
                }

                case NotifyCollectionChangedAction.Reset:
                    using (this.factory.RefreshTransaction())
                    {
                        this.Refresh(changes);
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(changes));
                }
            }
        }
예제 #2
0
        protected virtual void OnSourceCollectionChanged(IReadOnlyList <NotifyCollectionChangedEventArgs> changeCollection)
        {
            if (changeCollection == null || changeCollection.Count == 0)
            {
                return;
            }

            if (changeCollection.Count > 1)
            {
                this.Refresh();
                return;
            }

            var singleChange = changeCollection[0];

            try
            {
                switch (singleChange.Action)
                {
                case NotifyCollectionChangedAction.Add:
                {
                    var index = singleChange.NewStartingIndex;
                    var value = this.GetOrCreateValue(this.source.ElementAt(index), index);
                    this.mapped.Insert(index, value);
                    var changes = this.UpdateIndicesFrom(index + 1);
                    var change  = Diff.CreateAddEventArgs(value, index);
                    changes.Add(change);
                    base.Refresh(changes);
                    break;
                }

                case NotifyCollectionChangedAction.Remove:
                {
                    var index = singleChange.OldStartingIndex;
                    var value = this.mapped[index];
                    this.mapped.RemoveAt(index);
                    var changes = this.UpdateIndicesFrom(index);
                    var change  = Diff.CreateRemoveEventArgs(value, index);
                    changes.Add(change);
                    base.Refresh(changes);
                    break;
                }

                case NotifyCollectionChangedAction.Replace:
                {
                    var index    = singleChange.NewStartingIndex;
                    var value    = this.GetOrCreateValue(this.source.ElementAt(index), index);
                    var oldValue = this.mapped[singleChange.OldStartingIndex];
                    this.mapped[index] = value;
                    var change = Diff.CreateReplaceEventArgs(value, oldValue, index);
                    base.Refresh(new[] { change });
                    break;
                }

                case NotifyCollectionChangedAction.Move:
                {
                    var value = this.mapped[singleChange.OldStartingIndex];
                    this.mapped.RemoveAt(singleChange.OldStartingIndex);
                    this.mapped.Insert(singleChange.NewStartingIndex, value);
                    this.UpdateIndex(singleChange.OldStartingIndex);
                    this.UpdateIndex(singleChange.NewStartingIndex);
                    var change = Diff.CreateMoveEventArgs(this.mapped[singleChange.NewStartingIndex], singleChange.NewStartingIndex, singleChange.OldStartingIndex);
                    base.Refresh(new[] { change });
                    break;
                }

                case NotifyCollectionChangedAction.Reset:
                    this.Refresh();
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            catch (Exception)
            {
                this.Refresh(); // Resetting
            }
        }