/// <summary> /// Adds an operation to the undo buffer. /// </summary> /// <param name="operation">The operation.</param> /// <remarks> /// <para> /// This methods needs to be called for every <see cref="IUndoableOperation"/> before or after /// it is executed by calling its <see cref="IUndoableOperation.Do"/> method. Note: /// <see cref="Add"/> does not execute the <see cref="IUndoableOperation"/> it will only record /// the operation. /// </para> /// <para> /// After the operation is recorded in the undo buffer it can be undone and redone by calling /// <see cref="Undo"/> and <see cref="Redo"/>. /// </para> /// <para> /// The recording of operations in the undo buffer can be temporarily disabled by setting /// <see cref="AcceptChanges"/> to <see langword="false"/>. /// </para> /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="operation"/> is <see langword="null"/>. /// </exception> /// <seealso cref="AcceptChanges"/> public void Add(IUndoableOperation operation) { if (operation == null) { throw new ArgumentNullException("operation"); } if (AcceptChanges) { InternalUndoStack.EnqueueHead(operation); if (IsUndoGroupOpen) { _numberOfOperationsInGroup++; } if (InternalUndoStack.Count == 1) { OnPropertyChanged(new PropertyChangedEventArgs("CanUndo")); } ClearRedoStack(); if (!IsUndoGroupOpen) { EnforceSizeLimit(); } } }
/// <summary> /// Redoes the last undone operation. /// </summary> public void Redo() { AssertNoUndoGroupOpen(); if (InternalRedoStack.Count > 0) { IUndoableOperation operation = InternalRedoStack.DequeueHead(); InternalUndoStack.EnqueueHead(operation); operation.Do(); OnOperationRedone(); if (InternalRedoStack.Count == 0) { OnPropertyChanged(new PropertyChangedEventArgs("CanRedo")); } if (InternalUndoStack.Count == 1) { OnPropertyChanged(new PropertyChangedEventArgs("CanUndo")); } EnforceSizeLimit(); } }