예제 #1
0
		/// <summary>
		/// Construct a Change instance with actions for undo / redo.
		/// </summary>
		/// <param name="instance">The instance that changed.</param>
		/// <param name="propertyName">The property name that changed. (Case sensitive, used by reflection.)</param>
		/// <param name="oldValue">The old value of the property.</param>
		/// <param name="newValue">The new value of the property.</param>
		/// <returns>A Change that can be added to the UndoRoot's undo stack.</returns>
		public static Change GetChange(object instance, string propertyName, object oldValue, object newValue) {
			var undoMetadata = instance as IUndoMetadata;
			if (null != undoMetadata) {
				if (!undoMetadata.CanUndoProperty(propertyName, oldValue, newValue))
					return null;
			}

			var change = new DelegateChange(instance,
				() => instance.GetType().GetProperty(propertyName).SetValue(instance, oldValue, null),
				() => instance.GetType().GetProperty(propertyName).SetValue(instance, newValue, null),
				new ChangeKey<object, string>(instance, propertyName));
			return change;
		}
예제 #2
0
        /// <summary>
        /// Construct a Change instance with actions for undo / redo.
        /// </summary>
        /// <param name="instance">The instance that changed.</param>
        /// <param name="propertyName">The property name that changed. (Case sensitive, used by reflection.)</param>
        /// <param name="oldValue">The old value of the property.</param>
        /// <param name="newValue">The new value of the property.</param>
        /// <returns>A Change that can be added to the UndoRoot's undo stack.</returns>
        public static Change GetChange(object instance, string propertyName, object oldValue, object newValue)
        {
            var undoMetadata = instance as IUndoMetadata;

            if (null != undoMetadata)
            {
                if (!undoMetadata.CanUndoProperty(propertyName, oldValue, newValue))
                {
                    return(null);
                }
            }

            var change = new DelegateChange(instance,
                                            () => instance.GetType().GetProperty(propertyName).SetValue(instance, oldValue, null),
                                            () => instance.GetType().GetProperty(propertyName).SetValue(instance, newValue, null),
                                            new ChangeKey <object, string>(instance, propertyName));

            return(change);
        }
예제 #3
0
        /// <summary>
        /// Construct a Change instance with actions for undo / redo.
        /// </summary>
        /// <param name="instance">The instance that changed.</param>
        /// <param name="propertyName">The property name that exposes the collection that changed. (Case sensitive, used by reflection.)</param>
        /// <param name="collection">The collection that had an item added / removed.</param>
        /// <param name="e">The NotifyCollectionChangedEventArgs event args parameter, with info about the collection change.</param>
        /// <returns>A Change that can be added to the UndoRoot's undo stack.</returns>
        public static IList <Change> GetCollectionChange(object instance, string propertyName, object collection, NotifyCollectionChangedEventArgs e)
        {
            var undoMetadata = instance as IUndoMetadata;

            if (null != undoMetadata)
            {
                if (!undoMetadata.CanUndoCollectionChange(propertyName, collection, e))
                {
                    return(null);
                }
            }

            var ret = new List <Change>();

            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Add:
                ret.AddRange((from object item in e.NewItems let element = item let index = e.NewStartingIndex select new DelegateChange(instance, () => ((IList)collection).Remove(element), () => ((IList)collection).Insert(index, element), new ChangeKey <object, string, object>(instance, propertyName, item))));
                break;

            case NotifyCollectionChangedAction.Remove:
                ret.AddRange((from object item in e.OldItems let element = item let index = e.OldStartingIndex select new DelegateChange(instance, () => ((IList)collection).Insert(index, element), () => ((IList)collection).Remove(element), new ChangeKey <object, string, object>(instance, propertyName, item))));
                break;

#if !SILVERLIGHT
            case NotifyCollectionChangedAction.Move:
                int newIndex   = e.NewStartingIndex;
                int oldIndex   = e.OldStartingIndex;
                var moveChange = new DelegateChange(instance,
                                                    () => collection.GetType().GetMethod("Move").Invoke(collection, new object[] { newIndex, oldIndex }),
                                                    () => collection.GetType().GetMethod("Move").Invoke(collection, new object[] { oldIndex, newIndex }),
                                                    new ChangeKey <object, string, object>(instance, propertyName, new ChangeKey <int, int>(oldIndex, newIndex)));
                ret.Add(moveChange);
                break;
#endif
            case NotifyCollectionChangedAction.Replace:
                var replaceChange = new DelegateChange(
                    instance,
                    () => ((IList)collection)[e.NewStartingIndex] = e.OldItems[0],
                    () => ((IList)collection)[e.NewStartingIndex] = e.NewItems[0],
                    new ChangeKey <object, string, object>(instance, propertyName, new ChangeKey <object, object>(e.OldItems[0], e.NewItems[0]))
                    );
                ret.Add(replaceChange);
                break;

            case NotifyCollectionChangedAction.Reset:
                if (ThrowExceptionOnCollectionResets)
                {
                    throw new NotSupportedException("Undoing collection resets is not supported via the CollectionChanged event. The collection is already null, so the Undo system has no way to capture the set of elements that were previously in the collection.");
                }
                break;

            //IList collectionClone = collection.GetType().GetConstructor(new Type[] { collection.GetType() }).Invoke(new object[] { collection }) as IList;

            //var resetChange = new DelegateChange(
            //                        instance,
            //                        () =>
            //                        {
            //                            for (int i = 0; i < collectionClone.Count; i++) //for instead foreach to preserve the order
            //                                ((IList)collection).Add(collectionClone[i]);
            //                        },
            //                        () => collection.GetType().GetMethod("Clear").Invoke(collection, null),
            //                        new ChangeKey<object, string, object>(instance, propertyName, collectionClone)
            //                    );
            //ret.Add(resetChange);
            //break;

            default:
                throw new NotSupportedException();
            }

            return(ret);
        }
예제 #4
0
		/// <summary>
		/// Construct a Change instance with actions for undo / redo.
		/// </summary>
		/// <param name="instance">The instance that changed.</param>
		/// <param name="propertyName">The property name that exposes the collection that changed. (Case sensitive, used by reflection.)</param>
		/// <param name="collection">The collection that had an item added / removed.</param>
		/// <param name="e">The NotifyCollectionChangedEventArgs event args parameter, with info about the collection change.</param>
		/// <returns>A Change that can be added to the UndoRoot's undo stack.</returns>
		public static IList<Change> GetCollectionChange(object instance, string propertyName, object collection, NotifyCollectionChangedEventArgs e) {
			var undoMetadata = instance as IUndoMetadata;
			if (null != undoMetadata) {
				if (!undoMetadata.CanUndoCollectionChange(propertyName, collection, e))
					return null;
			}

			var ret = new List<Change>();

			switch (e.Action) {
				case NotifyCollectionChangedAction.Add:
					ret.AddRange((from object item in e.NewItems let element = item let index = e.NewStartingIndex select new DelegateChange(instance, () => ((IList)collection).Remove(element), () => ((IList)collection).Insert(index, element), new ChangeKey<object, string, object>(instance, propertyName, item))));
					break;

				case NotifyCollectionChangedAction.Remove:
					ret.AddRange((from object item in e.OldItems let element = item let index = e.OldStartingIndex select new DelegateChange(instance, () => ((IList)collection).Insert(index, element), () => ((IList)collection).Remove(element), new ChangeKey<object, string, object>(instance, propertyName, item))));
					break;

#if !SILVERLIGHT
				case NotifyCollectionChangedAction.Move:
					int newIndex = e.NewStartingIndex;
					int oldIndex = e.OldStartingIndex;
					var moveChange = new DelegateChange(instance,
						() => collection.GetType().GetMethod("Move").Invoke(collection, new object[] { newIndex, oldIndex }),
						() => collection.GetType().GetMethod("Move").Invoke(collection, new object[] { oldIndex, newIndex }),
						new ChangeKey<object, string, object>(instance, propertyName, new ChangeKey<int, int>(oldIndex, newIndex)));
					ret.Add(moveChange);
					break;
#endif
				case NotifyCollectionChangedAction.Replace:
					var replaceChange = new DelegateChange(
																	instance,
																	() => ((IList)collection)[e.NewStartingIndex] = e.OldItems[0],
																	() => ((IList)collection)[e.NewStartingIndex] = e.NewItems[0],
																	new ChangeKey<object, string, object>(instance, propertyName, new ChangeKey<object, object>(e.OldItems[0], e.NewItems[0]))
															);
					ret.Add(replaceChange);
					break;

				case NotifyCollectionChangedAction.Reset:
					if (ThrowExceptionOnCollectionResets)
						throw new NotSupportedException("Undoing collection resets is not supported via the CollectionChanged event. The collection is already null, so the Undo system has no way to capture the set of elements that were previously in the collection.");
					break;

				//IList collectionClone = collection.GetType().GetConstructor(new Type[] { collection.GetType() }).Invoke(new object[] { collection }) as IList;

				//var resetChange = new DelegateChange(
				//                        instance,
				//                        () =>
				//                        {
				//                            for (int i = 0; i < collectionClone.Count; i++) //for instead foreach to preserve the order
				//                                ((IList)collection).Add(collectionClone[i]);
				//                        },
				//                        () => collection.GetType().GetMethod("Clear").Invoke(collection, null),
				//                        new ChangeKey<object, string, object>(instance, propertyName, collectionClone)
				//                    );
				//ret.Add(resetChange);
				//break;

				default:
					throw new NotSupportedException();
			}

			return ret;
		}