object IList.this[int index]
        {
            get { return(this[index]); }

            set
            {
                var old = this[index];
                this.isUpdatingSourceItem = old;
                this[index] = (T)value;
                this.RefreshNow(Diff.CreateReplaceEventArgs(value, old, index));
                this.isUpdatingSourceItem = null;
            }
        }
Exemple #2
0
        protected virtual NotifyCollectionChangedEventArgs UpdateIndex(int index)
        {
            if (!this.factory.CanUpdateIndex)
            {
                return(null);
            }

            var key     = this.source.ElementAt(index);
            var updated = this.factory.UpdateIndex(key, index);
            var old     = this.mapped[index];

            if (ReferenceEquals(updated, old))
            {
                return(null);
            }

            this.mapped[index] = updated;
            return(Diff.CreateReplaceEventArgs(updated, old, index));
        }
Exemple #3
0
        /// <summary>
        /// Delegates updating of item at index to mapping factory.
        /// </summary>
        /// <param name="index">The index to update the item for.</param>
        /// <param name="createEventArgOnUpdate">If a <see cref="NotifyCollectionChangedEventArgs"/> for the update should be created.</param>
        /// <returns>
        /// The <see cref="NotifyCollectionChangedEventArgs"/> update causes or null.
        /// If the updated instance is the same reference null is returned.
        /// </returns>
        protected virtual NotifyCollectionChangedEventArgs UpdateAt(int index, bool createEventArgOnUpdate)
        {
            if (!this.factory.CanUpdateIndex)
            {
                return(null);
            }

            var old     = this.Tracker[index];
            var updated = this.factory.Update(this.Source.ElementAt(index), old, index);

            if (ReferenceEquals(updated, old))
            {
                return(null);
            }

            this.Tracker[index] = updated;
            return(createEventArgOnUpdate
                ? Diff.CreateReplaceEventArgs(updated, old, index)
                : null);
        }
Exemple #4
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));
                }
            }
        }
Exemple #5
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
            }
        }