利用單個對象表示變化的方法對示范應用程序Undo/Redo的實現將在以下步驟中討論
步驟1
我們將識別出那些需要支持Undo/Redo的操作。這裡有四個操作支持Undo/Redo。它們是::插入對象 、刪除對象、移動對象和調整對象的尺寸。我們將對矩形和橢圓支持Undo/Redo,這裡的容器是畫布。
步驟2
現在我們將識別出那些進一步處理Undo/Redo所需的保存的參數。幾何對象移動時其邊距改變,因此要 支持對象移動的Undo/Redo,要保存邊距。當對象改變尺寸時,它的高度、寬度和邊距改變。因此為支持 對象尺寸調整的Undo/Redo,我們需要保存高度、寬度和邊距。為了支持插入和刪除的Undo/Redo操作,我 們需要保存幾何對象的引用。
步驟3
現在我們得到包含邊距、高度、寬度、動作類型、幾何對象引用的ChangeRepresentationObject以支 持所有操作的Undo/Redo。這裡的幾何對象引用被保存以便我們在對其進行Undo/Redo時獲取。同樣使動作 類型enum代表插入、刪除、移動和調整尺寸操作。此動作類型enum被用作ChangeRepresentationObject的 一部分。
CollapseCopy Code
public enum ActionType
{
Delete = 0,
Move = 1,
Resize = 2,
Insert = 3
}
CollapseCopy Code
public class ChangeRepresentationObject
{
public ActionType Action;
public Point Margin;
public double Width;
public double height;
public FrameworkElement UIElement;
}
這裡,已附上使用單個對象表示變化的方法實現Undo/Redo的項目。
步驟4&5
然後我們將包含兩個ChangeRepresentationObject類型的棧的類命名為UndoRedo。一個棧用於撤銷操 作而另一個用於重做操作。類的代碼如下:
CollapseCopy Code
public partial class UnDoRedo : IUndoRedo
{
private Stack _UndoActionsCollection =
new Stack();
private Stack _RedoActionsCollection =
new Stack();
#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