Ejemplo n.º 1
0
        /// <summary>
        /// Raises the <see cref="Changed"/> event with the given parameters.
        /// </summary>
        /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param>
        /// <param name="changeType">The type of change that occurred.</param>
        /// <param name="oldValue">The old value of this content.</param>
        /// <param name="newValue">The new value of this content.</param>
        protected void NotifyContentChanged(object index, ContentChangeType changeType, object oldValue, object newValue)
        {
            var args = new ContentChangeEventArgs(this, index, changeType, oldValue, newValue);

            Changed?.Invoke(this, args);
            FinalizeChange?.Invoke(this, args);
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public override void Add(object newItem)
        {
            var collectionDescriptor = Descriptor as CollectionDescriptor;

            if (collectionDescriptor != null)
            {
                // Some collection (such as sets) won't add item at the end but at an arbitrary location.
                // Better send a null index in this case than sending a wrong value.
                var value = Value;
                var index = collectionDescriptor.IsList ? new Index(collectionDescriptor.GetCollectionCount(value)) : Index.Empty;
                var args  = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem);
                NotifyContentChanging(args);
                collectionDescriptor.Add(value, newItem);
                if (value.GetType().GetTypeInfo().IsValueType)
                {
                    var containerValue = Container.Value;
                    Member.Set(containerValue, value);
                }
                UpdateReferences();
                NotifyContentChanged(args);
            }
            else
            {
                throw new NotSupportedException("Unable to set the node value, the collection is unsupported");
            }
        }
 public AssetContentChangeEventArgs(ContentChangeEventArgs e, OverrideType previousOverride, OverrideType newOverride, ItemId itemId)
     : base(e.Content, e.Index, e.ChangeType, e.OldValue, e.NewValue)
 {
     PreviousOverride = previousOverride;
     NewOverride = newOverride;
     ItemId = itemId;
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Raises the <see cref="Changing"/> event with the given parameters.
        /// </summary>
        /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param>
        /// <param name="changeType">The type of change that occurred.</param>
        /// <param name="oldValue">The old value of this content.</param>
        /// <param name="newValue">The new value of this content.</param>
        protected void NotifyContentChanging(Index index, ContentChangeType changeType, object oldValue, object newValue)
        {
            var args = new ContentChangeEventArgs(this, index, changeType, oldValue, newValue);

            PrepareChange?.Invoke(this, args);
            Changing?.Invoke(this, args);
        }
Ejemplo n.º 5
0
        private void ContentPrepareChange(object sender, ContentChangeEventArgs e)
        {
            var node = e.Content.OwnerNode as IGraphNode;
            if (node != null)
            {
                foreach (var child in node.GetAllChildNodes())
                {
                    UnregisterNode(child);
                }
            }

            PrepareChange?.Invoke(sender, e);
        }
Ejemplo n.º 6
0
        private void ContentChanged(object sender, ContentChangeEventArgs e)
        {
            var node = e.Content.OwnerNode as IGraphNode;
            if (node != null)
            {
                foreach (var child in GetAllChildNodes(node))
                {
                    child.Content.Changing += ContentChanging;
                    child.Content.Changed += ContentChanged;
                }
            }

            Changed?.Invoke(sender, e);
        }
Ejemplo n.º 7
0
        private void Update(object newValue, Index index, bool sendNotification)
        {
            var oldValue = Retrieve(index);
            ContentChangeEventArgs args = null;

            if (sendNotification)
            {
                args = new ContentChangeEventArgs(this, index, ContentChangeType.ValueChange, oldValue, newValue);
                NotifyContentChanging(args);
            }

            if (!index.IsEmpty)
            {
                var collectionDescriptor = Descriptor as CollectionDescriptor;
                var dictionaryDescriptor = Descriptor as DictionaryDescriptor;
                if (collectionDescriptor != null)
                {
                    collectionDescriptor.SetValue(Value, index.Int, newValue);
                }
                else if (dictionaryDescriptor != null)
                {
                    dictionaryDescriptor.SetValue(Value, index.Value, newValue);
                }
                else
                {
                    throw new NotSupportedException("Unable to set the node value, the collection is unsupported");
                }
            }
            else
            {
                if (Container.Value == null)
                {
                    throw new InvalidOperationException("Container's value is null");
                }
                var containerValue = Container.Value;
                Member.Set(containerValue, newValue);

                if (Container.Value.GetType().GetTypeInfo().IsValueType)
                {
                    Container.UpdateFromMember(containerValue, Index.Empty);
                }
            }
            UpdateReferences();
            if (sendNotification)
            {
                NotifyContentChanged(args);
            }
        }
Ejemplo n.º 8
0
        /// <inheritdoc/>
        public override void Add(object newItem, Index itemIndex)
        {
            var collectionDescriptor = Descriptor as CollectionDescriptor;
            var dictionaryDescriptor = Descriptor as DictionaryDescriptor;

            if (collectionDescriptor != null)
            {
                var index = collectionDescriptor.IsList ? itemIndex : Index.Empty;
                var value = Value;
                var args  = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem);
                NotifyContentChanging(args);
                if (collectionDescriptor.GetCollectionCount(value) == itemIndex.Int || !collectionDescriptor.HasInsert)
                {
                    collectionDescriptor.Add(value, newItem);
                }
                else
                {
                    collectionDescriptor.Insert(value, itemIndex.Int, newItem);
                }
                if (value.GetType().GetTypeInfo().IsValueType)
                {
                    var containerValue = Container.Value;
                    Member.Set(containerValue, value);
                }
                UpdateReferences();
                NotifyContentChanged(args);
            }
            else if (dictionaryDescriptor != null)
            {
                var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionAdd, null, newItem);
                NotifyContentChanging(args);
                var value = Value;
                dictionaryDescriptor.AddToDictionary(value, itemIndex.Value, newItem);
                if (value.GetType().GetTypeInfo().IsValueType)
                {
                    var containerValue = Container.Value;
                    Member.Set(containerValue, value);
                }
                UpdateReferences();
                NotifyContentChanged(args);
            }
            else
            {
                throw new NotSupportedException("Unable to set the node value, the collection is unsupported");
            }
        }
Ejemplo n.º 9
0
        /// <inheritdoc/>
        public override void Add(object newItem, Index itemIndex)
        {
            var collectionDescriptor = Descriptor as CollectionDescriptor;
            var dictionaryDescriptor = Descriptor as DictionaryDescriptor;
            if (collectionDescriptor != null)
            {
                var index = collectionDescriptor.IsList ? itemIndex : Index.Empty;
                var value = Value;
                var args = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem);
                NotifyContentChanging(args);
                if (collectionDescriptor.GetCollectionCount(value) == itemIndex.Int || !collectionDescriptor.HasInsert)
                {
                    collectionDescriptor.Add(value, newItem);
                }
                else
                {
                    collectionDescriptor.Insert(value, itemIndex.Int, newItem);
                }
                if (value.GetType().GetTypeInfo().IsValueType)
                {
                    var containerValue = Container.Value;
                    Member.Set(containerValue, value);
                }
                UpdateReferences();
                NotifyContentChanged(args);
            }
            else if (dictionaryDescriptor != null)
            {
                var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionAdd, null, newItem);
                NotifyContentChanging(args);
                var value = Value;
                dictionaryDescriptor.AddToDictionary(value, itemIndex.Value, newItem);
                if (value.GetType().GetTypeInfo().IsValueType)
                {
                    var containerValue = Container.Value;
                    Member.Set(containerValue, value);
                }
                UpdateReferences();
                NotifyContentChanged(args);
            }
            else
                throw new NotSupportedException("Unable to set the node value, the collection is unsupported");

        }
Ejemplo n.º 10
0
        /// <inheritdoc/>
        public override void Remove(object item, Index itemIndex)
        {
            if (itemIndex.IsEmpty)
            {
                throw new ArgumentException(@"The given index should not be empty.", nameof(itemIndex));
            }
            var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionRemove, item, null);

            NotifyContentChanging(args);
            var collectionDescriptor = Descriptor as CollectionDescriptor;
            var dictionaryDescriptor = Descriptor as DictionaryDescriptor;
            var value = Value;

            if (collectionDescriptor != null)
            {
                if (collectionDescriptor.HasRemoveAt)
                {
                    collectionDescriptor.RemoveAt(value, itemIndex.Int);
                }
                else
                {
                    collectionDescriptor.Remove(value, item);
                }
            }
            else if (dictionaryDescriptor != null)
            {
                dictionaryDescriptor.Remove(value, itemIndex.Value);
            }
            else
            {
                throw new NotSupportedException("Unable to set the node value, the collection is unsupported");
            }

            if (value.GetType().GetTypeInfo().IsValueType)
            {
                var containerValue = Container.Value;
                Member.Set(containerValue, value);
            }
            UpdateReferences();
            NotifyContentChanged(args);
        }
Ejemplo n.º 11
0
 /// <inheritdoc/>
 public override void Add(object newItem)
 {
     var collectionDescriptor = Descriptor as CollectionDescriptor;
     if (collectionDescriptor != null)
     {
         // Some collection (such as sets) won't add item at the end but at an arbitrary location.
         // Better send a null index in this case than sending a wrong value.
         var value = Value;
         var index = collectionDescriptor.IsList ? new Index(collectionDescriptor.GetCollectionCount(value)) : Index.Empty;
         var args = new ContentChangeEventArgs(this, index, ContentChangeType.CollectionAdd, null, newItem);
         NotifyContentChanging(args);
         collectionDescriptor.Add(value, newItem);
         if (value.GetType().GetTypeInfo().IsValueType)
         {
             var containerValue = Container.Value;
             Member.Set(containerValue, value);
         }
         UpdateReferences();
         NotifyContentChanged(args);
     }
     else
         throw new NotSupportedException("Unable to set the node value, the collection is unsupported");
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Raises the <see cref="Changing"/> event with the given parameters.
 /// </summary>
 /// <param name="args">The arguments of the event.</param>
 protected void NotifyContentChanging(ContentChangeEventArgs args)
 {
     PrepareChange?.Invoke(this, args);
     Changing?.Invoke(this, args);
 }
Ejemplo n.º 13
0
        private void Update(object newValue, Index index, bool sendNotification)
        {
            var oldValue = Retrieve(index);
            ContentChangeEventArgs args = null;
            if (sendNotification)
            {
                args = new ContentChangeEventArgs(this, index, ContentChangeType.ValueChange, oldValue, newValue);
                NotifyContentChanging(args);
            }

            if (!index.IsEmpty)
            {
                var collectionDescriptor = Descriptor as CollectionDescriptor;
                var dictionaryDescriptor = Descriptor as DictionaryDescriptor;
                if (collectionDescriptor != null)
                {
                    collectionDescriptor.SetValue(Value, index.Int, newValue);
                }
                else if (dictionaryDescriptor != null)
                {
                    dictionaryDescriptor.SetValue(Value, index.Value, newValue);
                }
                else
                    throw new NotSupportedException("Unable to set the node value, the collection is unsupported");
            }
            else
            {
                if (Container.Value == null) throw new InvalidOperationException("Container's value is null");
                var containerValue = Container.Value;
                Member.Set(containerValue, newValue);

                if (Container.Value.GetType().GetTypeInfo().IsValueType)
                    Container.UpdateFromMember(containerValue, Index.Empty);
            }
            UpdateReferences();
            if (sendNotification)
            {
                NotifyContentChanged(args);
            }
        }
Ejemplo n.º 14
0
 private void ContentChanged(object sender, ContentChangeEventArgs e)
 {
     var path = GetPath(e.Content.OwnerNode);
     Changed?.Invoke(sender, new GraphContentChangeEventArgs(e, path));
 }
Ejemplo n.º 15
0
        private void ContentPrepareChange(object sender, ContentChangeEventArgs e)
        {
            var node = e.Content.OwnerNode as IGraphNode;
            var path = GetPath(e.Content.OwnerNode);
            if (node != null)
            {
                var visitor = new GraphVisitorBase();
                visitor.Visiting += UnregisterNode;
                switch (e.ChangeType)
                {
                    case ContentChangeType.ValueChange:
                        // The changed node itself is still valid, we don't want to unregister it
                        visitor.SkipRootNode = true;
                        visitor.Visit(node, path);
                        break;
                    case ContentChangeType.CollectionRemove:
                        if (node.Content.IsReference && e.OldValue != null)
                        {
                            var removedNode = node.Content.Reference.AsEnumerable[e.Index].TargetNode;
                            var removedNodePath = path?.PushIndex(e.Index);
                            if (removedNode != null)
                            {
                                visitor.Visit(removedNode, removedNodePath);
                            }
                        }
                        break;
                }
            }

            PrepareChange?.Invoke(sender, new GraphContentChangeEventArgs(e, path));
        }
Ejemplo n.º 16
0
        private void ContentFinalizeChange(object sender, ContentChangeEventArgs e)
        {
            var node = e.Content.OwnerNode as IGraphNode;
            var path = GetPath(e.Content.OwnerNode);
            if (node != null)
            {
                var visitor = new GraphVisitorBase();
                visitor.Visiting += RegisterNode;
                switch (e.ChangeType)
                {
                    case ContentChangeType.ValueChange:
                        // The changed node itself is still valid, we don't want to re-register it
                        visitor.SkipRootNode = true;
                        visitor.Visit(node, path);
                        break;
                    case ContentChangeType.CollectionAdd:
                        if (node.Content.IsReference && e.NewValue != null)
                        {
                            var index = e.Index;
                            IGraphNode addedNode;
                            if (!index.IsEmpty)
                            {
                                addedNode = node.Content.Reference.AsEnumerable[e.Index].TargetNode;
                            }
                            else
                            {
                                var reference = node.Content.Reference.AsEnumerable.First(x => x.TargetNode.Content.Retrieve() == e.NewValue);
                                index = reference.Index;
                                addedNode = reference.TargetNode;
                            }

                            if (addedNode != null)
                            {
                                var addedNodePath = path?.PushIndex(index);
                                visitor.Visit(addedNode, addedNodePath);
                            }
                        }
                        break;
                }
            }

            FinalizeChange?.Invoke(sender, new GraphContentChangeEventArgs(e, path));
        }
Ejemplo n.º 17
0
 /// <summary>
 /// Raises the <see cref="Changing"/> event with the given parameters.
 /// </summary>
 /// <param name="args">The arguments of the event.</param>
 protected void NotifyContentChanging(ContentChangeEventArgs args)
 {
     PrepareChange?.Invoke(this, args);
     Changing?.Invoke(this, args);
 }
 private void ContentChanged(object sender, ContentChangeEventArgs e)
 {
     Changed?.Invoke(sender, new GraphContentChangeEventArgs(e));
 }
Ejemplo n.º 19
0
        /// <inheritdoc/>
        public override void Remove(object item, Index itemIndex)
        {
            if (itemIndex.IsEmpty) throw new ArgumentException(@"The given index should not be empty.", nameof(itemIndex));
            var args = new ContentChangeEventArgs(this, itemIndex, ContentChangeType.CollectionRemove, item, null);
            NotifyContentChanging(args);
            var collectionDescriptor = Descriptor as CollectionDescriptor;
            var dictionaryDescriptor = Descriptor as DictionaryDescriptor;
            var value = Value;
            if (collectionDescriptor != null)
            {
                if (collectionDescriptor.HasRemoveAt)
                {
                    collectionDescriptor.RemoveAt(value, itemIndex.Int);                  
                }
                else
                {
                    collectionDescriptor.Remove(value, item);
                }
            }
            else if (dictionaryDescriptor != null)
            {
                dictionaryDescriptor.Remove(value, itemIndex.Value);
            }
            else
                throw new NotSupportedException("Unable to set the node value, the collection is unsupported");

            if (value.GetType().GetTypeInfo().IsValueType)
            {
                var containerValue = Container.Value;
                Member.Set(containerValue, value);
            }
            UpdateReferences();
            NotifyContentChanged(args);
        }
Ejemplo n.º 20
0
 /// <summary>
 /// Raises the <see cref="Changed"/> event with the given arguments.
 /// </summary>
 /// <param name="args">The arguments of the event.</param>
 protected void NotifyContentChanged(ContentChangeEventArgs args)
 {
     Changed?.Invoke(this, args);
     FinalizeChange?.Invoke(this, args);
 }
Ejemplo n.º 21
0
 /// <summary>
 /// Raises the <see cref="Changed"/> event with the given arguments.
 /// </summary>
 /// <param name="args">The arguments of the event.</param>
 protected void NotifyContentChanged(ContentChangeEventArgs args)
 {
     Changed?.Invoke(this, args);
     FinalizeChange?.Invoke(this, args);
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Raises the <see cref="Changed"/> event with the given parameters.
 /// </summary>
 /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param>
 /// <param name="oldValue">The old value of this content.</param>
 /// <param name="newValue">The new value of this content.</param>
 protected void NotifyContentChanged(object index, object oldValue, object newValue)
 {
     var args = new ContentChangeEventArgs(this, index, oldValue, newValue);
     Changed?.Invoke(this, args);
     FinalizeChange?.Invoke(this, args);
 }
Ejemplo n.º 23
0
 /// <summary>
 /// Raises the <see cref="Changing"/> event with the given parameters.
 /// </summary>
 /// <param name="index">The index where the change occurred, if applicable. <c>null</c> otherwise.</param>
 /// <param name="oldValue">The old value of this content.</param>
 /// <param name="newValue">The new value of this content.</param>
 protected void NotifyContentChanging(object index, object oldValue, object newValue)
 {
     var args = new ContentChangeEventArgs(this, index, oldValue, newValue);
     PrepareChange?.Invoke(this, args);
     Changing?.Invoke(this, args);
 }
Ejemplo n.º 24
0
 private void ContentChanged(object sender, ContentChangeEventArgs e)
 {
     Changed?.Invoke(sender, e);
 }
Ejemplo n.º 25
0
        private void ContentChanged(object sender, ContentChangeEventArgs e)
        {
            // Make sure that we have item ids everywhere we're supposed to.
            AssetCollectionItemIdHelper.GenerateMissingItemIds(e.Content.Retrieve());

            var node = (AssetNode)e.Content.OwnerNode;
            if (node.IsNonIdentifiableCollectionContent)
                return;

            // Create new ids for collection items
            var baseNode = (AssetNode)BaseContent?.OwnerNode;
            var isOverriding = !baseNode?.contentUpdating == true;
            var removedId = ItemId.Empty;
            switch (e.ChangeType)
            {
                case ContentChangeType.ValueChange:
                    break;
                case ContentChangeType.CollectionAdd:
                    {
                        var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor;
                        var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve());
                        // Compute the id we will add for this item
                        ItemId itemId;
                        if (baseNode?.contentUpdating == true)
                        {
                            var baseCollection = baseNode.Content.Retrieve();
                            var baseIds = CollectionItemIdHelper.GetCollectionItemIds(baseCollection);
                            itemId = itemIds.FindMissingId(baseIds);
                        }
                        else
                        {
                            itemId = restoringId != ItemId.Empty ? restoringId : ItemId.New();
                        }
                        // Add the id to the proper location (insert or add)
                        if (collectionDescriptor != null)
                        {
                            if (e.Index != Index.Empty)
                            {
                                itemIds.Insert(e.Index.Int, itemId);
                            }
                            else
                            {
                                throw new InvalidOperationException("An item has been added to a collection that does not have a predictable Add. Consider using NonIdentifiableCollectionItemsAttribute on this collection.");
                            }
                        }
                        else
                        {
                            itemIds[e.Index.Value] = itemId;
                        }
                    }
                    break;
                case ContentChangeType.CollectionRemove:
                    {
                        var collectionDescriptor = e.Content.Descriptor as CollectionDescriptor;
                        if (collectionDescriptor != null)
                        {
                            var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve());
                            removedId = itemIds.DeleteAndShift(e.Index.Int, isOverriding);
                        }
                        else
                        {
                            var itemIds = CollectionItemIdHelper.GetCollectionItemIds(e.Content.Retrieve());
                            removedId = itemIds.Delete(e.Index.Value, isOverriding);
                        }
                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }


            // Don't update override if propagation from base is disabled.
            if (PropertyGraph?.Container?.PropagateChangesFromBase == false)
                return;

            // Mark it as New if it does not come from the base
            if (!baseNode?.contentUpdating == true && !ResettingOverride)
            {
                if (e.ChangeType != ContentChangeType.CollectionRemove)
                {
                    if (e.Index == Index.Empty)
                    {
                        OverrideContent(!ResettingOverride);
                    }
                    else
                    {
                        OverrideItem(!ResettingOverride, e.Index);
                    }
                }
                else
                {
                    OverrideDeletedItem(true, removedId);
                }
            }
        }
Ejemplo n.º 26
0
        private void AssetContentChanged(object sender, ContentChangeEventArgs e)
        {
            var previousOverride = previousOverrides[e.Content.OwnerNode];
            previousOverrides.Remove(e.Content.OwnerNode);

            var itemId = ItemId.Empty;
            var overrideValue = OverrideType.Base;
            var node = (AssetNode)e.Content.OwnerNode;
            if (e.ChangeType == ContentChangeType.ValueChange || e.ChangeType == ContentChangeType.CollectionAdd)
            {
                if (e.Index == Index.Empty)
                {
                    // No index, we're changing an object that is not in a collection, let's just retrieve it's override status.
                    overrideValue = node.GetContentOverride();
                }
                else
                {
                    // We're changing an item of a collection. If the collection has identifiable items, retrieve the override status of the item.
                    if (!node.IsNonIdentifiableCollectionContent)
                    {
                        overrideValue = node.GetItemOverride(e.Index);
                    }
                    // Also retrieve the id of the modified item (this should fail only if the collection doesn't have identifiable items)
                    CollectionItemIdentifiers ids;
                    if (CollectionItemIdHelper.TryGetCollectionItemIds(e.Content.Retrieve(), out ids))
                    {
                        ids.TryGet(e.Index.Value, out itemId);
                    }
                }
            }
            else
            {
                // When deleting we are always overriding (unless there is no base)
                overrideValue = !((AssetNode)node.BaseContent?.OwnerNode)?.contentUpdating == true ? OverrideType.New : OverrideType.Base;
                itemId = removedItemIds[e.Content.OwnerNode];
                removedItemIds.Remove(e.Content.OwnerNode);
            }

            Changed?.Invoke(sender, new AssetContentChangeEventArgs(e, previousOverride, overrideValue, itemId));
        }
Ejemplo n.º 27
0
        private void OnBaseContentChanged(ContentChangeEventArgs e, IContent assetContent)
        {
            // Ignore base change if propagation is disabled.
            if (!Container.PropagateChangesFromBase)
                return;

            UpdatingPropertyFromBase = true;
            // TODO: we want to refresh the base only starting from the modified node!
            RefreshBase(baseGraph);
            var rootNode = (AssetNode)assetContent.OwnerNode;
            var visitor = CreateReconcilierVisitor();
            visitor.Visiting += (node, path) => ReconcileWithBaseNode((AssetNode)node);
            visitor.Visit(rootNode);
            UpdatingPropertyFromBase = false;

            BaseContentChanged?.Invoke(e, assetContent);
        }
 private void ContentChanged(object sender, ContentChangeEventArgs e)
 {
     if (!updatingValue)
         OnPropertyChanged(nameof(VirtualObservableNode<object>.TypedValue));
 }
Ejemplo n.º 29
0
 private void AssetContentChanging(object sender, ContentChangeEventArgs e)
 {
     var overrideValue = OverrideType.Base;
     var node = (AssetNode)e.Content.OwnerNode;
     if (e.ChangeType == ContentChangeType.ValueChange || e.ChangeType == ContentChangeType.CollectionRemove)
     {
         // For value change and remove, we store the current override state.
         if (e.Index == Index.Empty)
         {
             overrideValue = node.GetContentOverride();
         }
         else if (!node.IsNonIdentifiableCollectionContent)
         {
             overrideValue = node.GetItemOverride(e.Index);
         }
     }
     if (e.ChangeType == ContentChangeType.CollectionRemove)
     {
         // For remove, we also collect the id of the item that will be removed, so we can pass it to the Changed event.
         var itemId = ItemId.Empty;
         CollectionItemIdentifiers ids;
         if (CollectionItemIdHelper.TryGetCollectionItemIds(e.Content.Retrieve(), out ids))
         {
             ids.TryGet(e.Index.Value, out itemId);
         }
         removedItemIds[e.Content.OwnerNode] = itemId;
     }
     if (e.ChangeType == ContentChangeType.CollectionAdd && !node.IsNonIdentifiableCollectionContent)
     {
         // If the change is an add, we set the previous override as New so the Undo will try to remove the item instead of resetting to the base value
         previousOverrides[e.Content.OwnerNode] = OverrideType.New;
     }
     previousOverrides[e.Content.OwnerNode] = overrideValue;
 }