示例应用程序描述
这个示范WPF绘制应用程序用来作为结合Undo/Redo操作的案例。该WPF应用程序示例支持四种操作:插入对象、删除对象、移动对象和调整对象的尺寸,它还有两种类型的几何对象:矩形和多边形。它使用画布作为包含这些几何对象的容器。
现在,在此系列文章中,我们可以看到如何让这四个操作支持Undo/Redo。在第一部分,使用单个对象表示变化的方法实现。在第二部分,使用命令模式实现而在第三部分,使用备忘录模式实现。
使用命令模式实现示例应用程序的Undo/Redo
利用命令模式对示范应用程序Undo/Redo的实现将在以下步骤中讨论:
步骤1
在示范应用程序中有四种操作,它们是移动、调整尺寸、插入和删除。对象是矩形、椭圆,而容器是一个WPF画布。
步骤2
现在我们要为四种操作创建四个继承ICommand接口的命令类。
class MoveCommand : ICommand
{
private Thickness _ChangeOfMargin;
private FrameworkElement _UiElement;
public MoveCommand(Thickness margin, FrameworkElement uiElement)
{
_ChangeOfMargin = margin;
_UiElement = uiElement;
}
#region ICommand Members
public void Execute()
{
_UiElement.Margin = new Thickness(_UiElement.Margin.Left +
_ChangeOfMargin.Left, _UiElement.Margin.Top
+ _ChangeOfMargin.Top, _UiElement.Margin.Right +
_ChangeOfMargin.Right, _UiElement.Margin.Bottom +
_ChangeOfMargin.Bottom);
}
public void UnExecute()
{
_UiElement.Margin = new Thickness(_UiElement.Margin.Left -
_ChangeOfMargin.Left, _UiElement.Margin.Top -
_ChangeOfMargin.Top, _UiElement.Margin.Right -
_ChangeOfMargin.Right, _UiElement.Margin.Bottom -
_ChangeOfMargin.Bottom);
}
#endregion
}
{
private Thickness _ChangeOfMargin;
private FrameworkElement _UiElement;
public MoveCommand(Thickness margin, FrameworkElement uiElement)
{
_ChangeOfMargin = margin;
_UiElement = uiElement;
}
#region ICommand Members
public void Execute()
{
_UiElement.Margin = new Thickness(_UiElement.Margin.Left +
_ChangeOfMargin.Left, _UiElement.Margin.Top
+ _ChangeOfMargin.Top, _UiElement.Margin.Right +
_ChangeOfMargin.Right, _UiElement.Margin.Bottom +
_ChangeOfMargin.Bottom);
}
public void UnExecute()
{
_UiElement.Margin = new Thickness(_UiElement.Margin.Left -
_ChangeOfMargin.Left, _UiElement.Margin.Top -
_ChangeOfMargin.Top, _UiElement.Margin.Right -
_ChangeOfMargin.Right, _UiElement.Margin.Bottom -
_ChangeOfMargin.Bottom);
}
#endregion
}
由于移动对象仅改变了几何对象的边距,移动命令将包含边距的变化,几何对象的引用。在移动命令中,Execute方法通过增加边距变化改变几何对象UIelement,而Unexecute方法通过减去刚应用的变化来撤销操作。这样,它减掉了几何对象UIelement的边距变化。
class ResizeCommand : ICommand
{
private Thickness _ChangeOfMargin;
private double _ChangeofWidth;
private double _Changeofheight;
private FrameworkElement _UiElement;
public ResizeCommand(Thickness margin, double width,
double height, FrameworkElement uiElement)
{
_ChangeOfMargin = margin;
_ChangeofWidth = width;
_Changeofheight = height;
_UiElement = uiElement;
}
#region ICommand Members
public void Execute()
{
_UiElement.Height = _UiElement.Height + _Changeofheight;
_UiElement.Width = _UiElement.Width + _ChangeofWidth;
_UiElement.Margin = new Thickness
(_UiElement.Margin.Left + _ChangeOfMargin.Left,
_UiElement.Margin.Top
+ _ChangeOfMargin.Top, _UiElement.Margin.Right +
_ChangeOfMargin.Right, _UiElement.Margin.Bottom +
_ChangeOfMargin.Bottom);
}
public void UnExecute()
{
_UiElement.Height = _UiElement.Height - _Changeofheight;
_UiElement.Width = _UiElement.Width - _ChangeofWidth;
_UiElement.Margin = new Thickness(_UiElement.Margin.Left -
_ChangeOfMargin.Left, _UiElement.Margin.Top -
_ChangeOfMargin.Top, _UiElement.Margin.Right -
_ChangeOfMargin.Right, _UiElement.Margin.Bottom -
_ChangeOfMargin.Bottom);
}
#endregion
}
{
private Thickness _ChangeOfMargin;
private double _ChangeofWidth;
private double _Changeofheight;
private FrameworkElement _UiElement;
public ResizeCommand(Thickness margin, double width,
double height, FrameworkElement uiElement)
{
_ChangeOfMargin = margin;
_ChangeofWidth = width;
_Changeofheight = height;
_UiElement = uiElement;
}
#region ICommand Members
public void Execute()
{
_UiElement.Height = _UiElement.Height + _Changeofheight;
_UiElement.Width = _UiElement.Width + _ChangeofWidth;
_UiElement.Margin = new Thickness
(_UiElement.Margin.Left + _ChangeOfMargin.Left,
_UiElement.Margin.Top
+ _ChangeOfMargin.Top, _UiElement.Margin.Right +
_ChangeOfMargin.Right, _UiElement.Margin.Bottom +
_ChangeOfMargin.Bottom);
}
public void UnExecute()
{
_UiElement.Height = _UiElement.Height - _Changeofheight;
_UiElement.Width = _UiElement.Width - _ChangeofWidth;
_UiElement.Margin = new Thickness(_UiElement.Margin.Left -
_ChangeOfMargin.Left, _UiElement.Margin.Top -
_ChangeOfMargin.Top, _UiElement.Margin.Right -
_ChangeOfMargin.Right, _UiElement.Margin.Bottom -
_ChangeOfMargin.Bottom);
}
#endregion
}