Exemplo n.º 1
0
        void ObservableCollectionChanged(object sender, NotifyCollectionChangingEventArgs e)
        {
            if (!TrackChanges)
            {
                return;
            }

            ThrowIfFromDifferentThread();

            if (ExcludedTypes.Contains(sender.GetType()))
            {
                return;
            }

            if (!handlingDisconnected)
            {
                //we got an event through the normal path, so we're sure this object is still connected
                UnsubscribeDisconnected(sender);
            }

            NotifyCollectionChangeMemento memento;
            var key = new CollectionChangeKey(sender, e.Item, e.Action);
            collectionChangeMementos.TryGetValue(key, out memento);

            if (memento == null)
            {
                throw new NotSupportedException("CollectionChanged received without CollectionChanging");
            }

            memento.RememberNewValues(sender, e);
            collectionChangeMementos.Remove(key);

            lastCollectionChangeMemento = memento;

            // exceptional situation, same object!
            if (!TypeUtils.IsAggregationList(sender))
            {
                if (ReferenceEquals(memento.OldValue, memento.NewValue))
                {
                    UnsubscribeDisconnected(memento.OldValue);
                }
                UnsubscribeDisconnected(memento.NewValue); // newly added value
            }

            LogCollectionChanged(memento, e);
        }
Exemplo n.º 2
0
 protected bool Equals(CollectionChangeKey other)
 {
     return sender.Equals(other.sender) && item.Equals(other.item) && action == other.action;
 }
Exemplo n.º 3
0
        void ObservableCollectionChanging(object sender, NotifyCollectionChangingEventArgs e)
        {
            if (!TrackChanges)
            {
                return;
            }
            ThrowIfFromDifferentThread();

            if (ExcludedTypes.Contains(sender.GetType()))
            {
                return;
            }

            if (!handlingDisconnected)
            {
                //we got an event through the normal path, so we're sure this object is still connected
                UnsubscribeDisconnected(sender);
            }

            // normally this will not happen unless event handlers are subscribed before undo/redo, check nevertheless
            if (e.Cancel)
            {
                log.DebugFormat("CollectionChanging event was cancelled, skipping undo");
                return;
            }

            FixCancelledCollectionChangingEvents();
            var key = new CollectionChangeKey(sender, e.Item, e.Action);
            if (collectionChangeMementos.ContainsKey(key))
            {
                if (handlingDisconnected)
                {
                    return; //already received
                }

                throw new NotSupportedException("The same CollectionChanging event fired twice (probably two different event paths)");
            }

            if (restoringMemento != null)
            {
                if (!IsCollectionChangeEventPartOfRestore(sender, e.Index))
                {
                    throw new InvalidOperationException("Side-effect code detected (code which changes object tree in setters or in event handlers) which is not marked with [EditAction]");
                }
            }

            if (eventCascadeCallLevel > 1 && !handlingDisconnected)
            {
                if (eventCascadeCallLevel < expectedEventCascadeCallLevel)
                {
                    expectedEventCascadeCallLevel = eventCascadeCallLevel;
                }

                // we must be in a side-effect
                if (expectedEventCascadeCallLevel != eventCascadeCallLevel)
                {
                    log.DebugFormat("CascadeEventLevel: {0}, ExpectedCascadeEventLevel: {1}", eventCascadeCallLevel, expectedEventCascadeCallLevel); 
                    throw new InvalidOperationException("Side-effect code detected (code which changes object tree in setters or in event handlers) which is not marked with [EditAction]");
                }
            }

            var memento = (NotifyCollectionChangeMemento)mementoStack.Peek();
            memento.RememberOldValues(sender, e);

            collectionChangeMementos[key] = memento;

            if (!handlingDisconnected && !TypeUtils.IsAggregationList(sender))
            {
                if (restoringMemento == null)
                {
                    HandleIfTransactional(memento.OldValue, true);
                }
                SubscribeDisconnected(memento.OldValue); // listen to the changes in disconnected objects
            }
        }