internal void UpdateValue()
            {
                var oldValue         = this.Value.OldValue;
                var newPropertyValue = _propertyInfo.GetValue(_propertyOwnerObj, null);

                if (!_undoRedoService.IsUndoing && !_undoRedoService.IsRedoing)
                {
                    RecordValueChange(newPropertyValue, oldValue);
                }

                this.Value = RecordedElementFactory.Create(_undoRedoService, _propertyInfo.GetValue(_propertyOwnerObj, null));
            }
        public CollectionChangedRecordedElement(IUndoRedoService undoRedoService, IList objAsIList, INotifyCollectionChanged objAsNotifyCollectionChanged)
            : base(objAsNotifyCollectionChanged)
        {
            if (!ReferenceEquals(objAsIList, objAsNotifyCollectionChanged))
            {
                throw new ArgumentException("Arguments should have the same references");
            }

            _undoRedoService = undoRedoService;
            _objAsIList      = objAsIList;
            _listAsNotifyCollectionChanged = objAsNotifyCollectionChanged;
            _listAsNotifyCollectionChanged.CollectionChanged += OnCollectionChanged;

            foreach (var item in _objAsIList)
            {
                _recordedElementItems.Add(RecordedElementFactory.Create(undoRedoService, item));
            }
        }
        private void SynchronizeWithRecordedItems(NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
        {
            switch (notifyCollectionChangedEventArgs.Action)
            {
            case NotifyCollectionChangedAction.Add:
            {
                var insertionIndex = notifyCollectionChangedEventArgs.NewStartingIndex;
                foreach (var newItem in notifyCollectionChangedEventArgs.NewItems)
                {
                    _recordedElementItems.Insert(insertionIndex, RecordedElementFactory.Create(_undoRedoService, newItem));
                }
                break;
            }

            case NotifyCollectionChangedAction.Move:
            {
                var oldStartingIndex = notifyCollectionChangedEventArgs.OldStartingIndex;

                var itemsToMove = new List <RecordedElement>();
                foreach (var item in notifyCollectionChangedEventArgs.OldItems)
                {
                    itemsToMove.Add(_recordedElementItems[oldStartingIndex]);
                    _recordedElementItems.RemoveAt(oldStartingIndex++);
                }

                var newStartingIndex = notifyCollectionChangedEventArgs.NewStartingIndex;
                foreach (var item in itemsToMove)
                {
                    _recordedElementItems.Insert(newStartingIndex++, item);
                }

                break;
            }

            case NotifyCollectionChangedAction.Remove:
            {
                foreach (var removedItem in notifyCollectionChangedEventArgs.OldItems)
                {
                    _recordedElementItems[notifyCollectionChangedEventArgs.OldStartingIndex].Release();
                    _recordedElementItems.RemoveAt(notifyCollectionChangedEventArgs.OldStartingIndex);
                }

                break;
            }

            case NotifyCollectionChangedAction.Replace:
            {
                var index = notifyCollectionChangedEventArgs.NewStartingIndex;
                foreach (var newItem in notifyCollectionChangedEventArgs.NewItems)
                {
                    _recordedElementItems[index].Release();
                    _recordedElementItems[index] = RecordedElementFactory.Create(_undoRedoService, newItem);
                    index++;
                }
                break;
            }

            case NotifyCollectionChangedAction.Reset:
            {
                foreach (var item in _recordedElementItems)
                {
                    item.Release();
                }
                _recordedElementItems.Clear();
                break;
            }

            default:
            {
                throw new Exception("unknown " + typeof(NotifyCollectionChangedAction).Name + " = " + notifyCollectionChangedEventArgs.Action);
            }
            }
        }
            internal static Property Create(IUndoRedoService undoRedoService, INotifyPropertyChanged objAsNotifyPropertyChanged, IsRecordableAttribute isRecordableAttribute, PropertyInfo propertyInfo)
            {
                var recordableWithFilterAttribute = isRecordableAttribute as IsRecordableWithFilterAttribute;

                Property property;

                if (recordableWithFilterAttribute != null)
                {
                    property = new FilteredChangeRecordProperty(undoRedoService, objAsNotifyPropertyChanged, propertyInfo, RecordedElementFactory.Create(undoRedoService, propertyInfo.GetValue(objAsNotifyPropertyChanged, null)), recordableWithFilterAttribute);
                }
                else
                {
                    property = new EveryChangeRecordProperty(undoRedoService, objAsNotifyPropertyChanged, propertyInfo, RecordedElementFactory.Create(undoRedoService, propertyInfo.GetValue(objAsNotifyPropertyChanged, null)), isRecordableAttribute);
                }
                return(property);
            }