技术开发 频道

C#中使用单个对象的方法实现Undo/Redo

  步骤4&5

  然后我们将包含两个ChangeRepresentationObject类型的栈的类命名为UndoRedo。一个栈用于撤销操作而另一个用于重做操作。类的代码如下:

Collapse  Copy Code
  
public partial class UnDoRedo : IUndoRedo
    {
        
private Stack<ChangeRepresentationObject> _UndoActionsCollection =
    
new Stack<ChangeRepresentationObject>();
        
private Stack<ChangeRepresentationObject> _RedoActionsCollection =
    
new Stack<ChangeRepresentationObject>();
        
        
#region IUndoRedo Members

        
public void Undo(int level)
        {
            
for (int i = 1; i <= level; i++)
            {
                
if (_UndoActionsCollection.Count == 0) return;

                ChangeRepresentationObject Undostruct
= _UndoActionsCollection.Pop();
                
if (Undostruct.Action == ActionType.Delete)
                {
                    Container.Children.Add(Undostruct.UiElement);
                    
this.RedoPushInUnDoForDelete(Undostruct.UiElement);
                }
                
else if (Undostruct.Action == ActionType.Insert)
                {
                    Container.Children.Remove(Undostruct.UiElement);
                    
this.RedoPushInUnDoForInsert(Undostruct.UiElement);
                }
                
else if (Undostruct.Action == ActionType.Resize)
                {
                    
if (_UndoActionsCollection.Count != 0)
                    {
                        Point previousMarginOfSelectedObject
= new Point
   (((FrameworkElement)Undostruct.UiElement).Margin.Left,
                            ((FrameworkElement)Undostruct.UiElement).Margin.Top);
                        
this.RedoPushInUnDoForResize(previousMarginOfSelectedObject,
   Undostruct.UiElement.Width,
                            Undostruct.UiElement.Height, Undostruct.UiElement);
                        Undostruct.UiElement.Margin
= new Thickness
   (Undostruct.Margin.X, Undostruct.Margin.Y,
0, 0);
                        Undostruct.UiElement.Height
= Undostruct.height;
                        Undostruct.UiElement.Width
= Undostruct.Width;
                    }
                }
                
else if (Undostruct.Action == ActionType.Move)
                {
                    Point previousMarginOfSelectedObject
= new Point
   (((FrameworkElement)Undostruct.UiElement).Margin.Left,
                        ((FrameworkElement)Undostruct.UiElement).Margin.Top);
                    
this.RedoPushInUnDoForMove(previousMarginOfSelectedObject,
       Undostruct.UiElement);
                    Undostruct.UiElement.Margin
= new Thickness
   (Undostruct.Margin.X, Undostruct.Margin.Y,
0, 0);
                }
            }
        }

        
public void Redo(int level)
        {
            
for (int i = 1; i <= level; i++)
            {
                
if (_RedoActionsCollection.Count == 0) return;

                ChangeRepresentationObject Undostruct
= _RedoActionsCollection.Pop();
                
if (Undostruct.Action == ActionType.Delete)
                {
                    Container.Children.Remove(Undostruct.UiElement);
                    
this.PushInUnDoForDelete(Undostruct.UiElement);
                }
                
else if (Undostruct.Action == ActionType.Insert)
                {
                    Container.Children.Add(Undostruct.UiElement);
                    
this.PushInUnDoForInsert(Undostruct.UiElement);
                }
                
else if (Undostruct.Action == ActionType.Resize)
                {
                    Point previousMarginOfSelectedObject
= new Point
   (((FrameworkElement)Undostruct.UiElement).Margin.Left,
                        ((FrameworkElement)Undostruct.UiElement).Margin.Top);
                    
this.PushInUnDoForResize(previousMarginOfSelectedObject,
      Undostruct.UiElement.Width,
                        Undostruct.UiElement.Height, Undostruct.UiElement);
                    Undostruct.UiElement.Margin
= new Thickness
   (Undostruct.Margin.X, Undostruct.Margin.Y,
0, 0);
                    Undostruct.UiElement.Height
= Undostruct.height;
                    Undostruct.UiElement.Width
= Undostruct.Width;
                }
                
else if (Undostruct.Action == ActionType.Move)
                {
                    Point previousMarginOfSelectedObject
= new Point
   (((FrameworkElement)Undostruct.UiElement).Margin.Left,
                        ((FrameworkElement)Undostruct.UiElement).Margin.Top);
                    
this.PushInUnDoForMove(previousMarginOfSelectedObject,
       Undostruct.UiElement);
                    Undostruct.UiElement.Margin
= new Thickness
    (Undostruct.Margin.X, Undostruct.Margin.Y,
0, 0);
                }
            }
        }
        
public void InsertObjectforUndoRedo(ChangeRepresentationObject dataobject)
        {
            _UndoActionsCollection.Push(dataobject);_RedoActionsCollection.Clear();
        }
      
#endregion

  步骤6

  在完成每个操作前,调用InsertObjectforUndoRedo方法。当用户界面上Undo被点击,我们调用UndoRedo类的Undo方法,而当用户界面上Redo被点击,我们调用UndoRedo类的redo方法。

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

  使用单个对象表示变化的方法时的变更管理

  如果你想要用单个对象表示变化的方法来为新的操作支持Undo/Redo时,你不得不作一些改变。你不得不修改表示变化的对象,动作类型Enum并改变Undo/Redo方法的代码。所以,它的可维护性很低。

  使用单个对象表示变化的方法的优缺点

  它的优点是实现简单,而不需要知道任何的设计模式,你就可以实现Undo/Redo。

  可维护性很低。代表该方法的对象包含很多额外信息,因为这里,单个对象用来容纳所有动作类型的数据。例如,对移动而言,我们只需保存移动相关的数据,而对调整尺寸,我们应该仅保存该操作相关的数据。所以,我们在保存冗余的数据。随着操作数目的增加,冗余也在增加。这并不是好的面向对象的设计。

0
相关文章