技术开发 频道

C#中使用命令模式实现Undo/Redo

  步骤3

  现在我们将根据通用方法的描述实现UndoRedo类。

  public class UnDoRedo
    {
        
private Stack<ICommand> _Undocommands = new Stack<ICommand>();
        
private Stack<ICommand> _Redocommands = new Stack<ICommand>();

        
private Canvas _Container;

        
public Canvas Container
        {
            
get { return _Container; }
            
set { _Container = value; }
        }

        
public void Redo(int levels)
        {
            
for (int i = 1; i <= levels; i++)
            {
                
if (_Redocommands.Count != 0)
                {
                    ICommand command
= _Redocommands.Pop();
                    command.Execute();
                    _Undocommands.Push(command);
                }

            }
        }

        
public void Undo(int levels)
        {
            
for (int i = 1; i <= levels; i++)
            {
                
if (_Undocommands.Count != 0)
                {
                    ICommand command
= _Undocommands.Pop();
                    command.UnExecute();
                    _Redocommands.Push(command);
                }

            }
        }

        
#region UndoHelperFunctions

        
public void InsertInUnDoRedoForInsert(FrameworkElement ApbOrDevice)
        {
            ICommand cmd
= new InsertCommand(ApbOrDevice, Container);
            _Undocommands.Push(cmd);_Redocommands.Clear();
        }

        
public void InsertInUnDoRedoForDelete(FrameworkElement ApbOrDevice)
        {
            ICommand cmd
= new DeleteCommand(ApbOrDevice, Container);
            _Undocommands.Push(cmd);_Redocommands.Clear();
        }

        
public void InsertInUnDoRedoForMove
  (Point margin, FrameworkElement UIelement)
        {
            ICommand cmd
= new MoveCommand(new Thickness
   (margin.X, margin.Y,
0, 0), UIelement);
            _Undocommands.Push(cmd);_Redocommands.Clear();
        }

        
public void InsertInUnDoRedoForResize
(Point margin,
double width, double height, FrameworkElement UIelement)
        {
            ICommand cmd
= new ResizeCommand(new Thickness
  (margin.X, margin.Y,
0, 0), width, height, UIelement);
            _Undocommands.Push(cmd);_Redocommands.Clear();
        }

        
#endregion
    }

 

  第一个栈_Undocommands进行撤销操作而第二个栈_Redocommands进行重做操作。当InsertInUnDoRedo方法被调用,Icommand对象被插入使之可以进行撤销操作并清空Redostack。这里,级别决定了你想要撤销的次数。这就是为什么你级别是多少,就不得不在undoredo方法中运行撤销,重做方法多少次。

  步骤4

  当你完成应用程序中不同的操作,创建该操作类型的命令对象并调用InsertInUnDoRedo方法将其压入Undo/Redo系统。当用户界面上点击Undo,我们调用UndoRedo类的Undo方法,而当用户界面上点击Redo,我们调用UndoRedo类的redo方法。

  这里,我们没有明确设置Undo栈和Redo栈的大小,因此,应用程序能具有的状态数目取决于系统的内存。

  使用命令模式时的变更管理

  当你需要为你应用程序中新的操作支持Undo/Redo时,你只需要添加一个新的命令对象。我认为这具有很好的可维护性。

  使用命令模式的优缺点

  它的可维护性很好而且没有任何冗余信息。它不是内存密集型,从我的观点来看,命令模式是实现多级Undo/Redo的最好方式。
命令模式的唯一缺点在于你不得不使命令的类型与操作的数目相等而无论一个操作是小或大。随着操作地增加,命令也在增加。

0
相关文章