无法理解实现撤消/重做功能,我应该使用 Stack 吗?



我现在有点糊涂了,我猜我又糊涂了。

我需要实现一个撤消和重做功能的形式。为简单起见,假设我只保存修改过的控件和它离开焦点时的值。

如何保存这些信息,让我可以在"时间轴"中来回移动。

我想过用Stack,但当我在测试我的小演示时,我得了轻微的动脉瘤,所以我在这里。

需要代码,不是真的,但会有帮助。我对我需要实现的算法更感兴趣。有什么建议吗?

是的,您将使用堆栈。有几种方法可以做到;阅读这些参考文献:

http://en.wikipedia.org/wiki/Command_pattern

http://en.wikipedia.org/wiki/Memento_pattern

堆栈是完美的,如果你推一个"更改"到它,当撤消弹出一个"更改"。然后将弹出的更改推入代表重做的另一个堆栈。在未来的某个时刻,希望在豁免时,你清除了两个堆栈。

实际上并没有那么简单,因为你需要记录变化的类型,了解新旧值等。所以当你从撤销堆栈弹出时,你弹出的东西必须描述先前的值是什么以及它被设置为哪个控件。

对于重做堆栈来说,它需要了解新值是什么以及它去了哪里。但是,是的,两个堆栈的想法对于自制撤销-重做来说是一个好的开始。

基于业务对象的撤销的一个很好的例子是CSLA。. NET,其中UndoableBase:

http://www.lhotka.net/cslanet/

http://www.koders.com/csharp/fidCF6AB2CF035B830FF6E40AA22C8AE7B135BE1FC0.aspx?s=serializationinfo

然而,这记录了对象状态的快照,因此它将比基于表单的概念更高级。然而,里昂证券。. NET提供了完整的数据绑定支持,因此从UndoableBase继承的数据绑定对象自然会在UI中支持撤销(而不是重做)。

我将使用IUndoableAction接口。实现可以存储需要完成和撤消的任何数据。那么,是的,我会使用Stack来保存它们。

interface IUndoableAction
{
    void Do();
    void Undo();
}
Stack<IUndoableAction> Actions;

每一种操作都将实现Do和Undo方法。

那么,在某个地方会有这两个方法:

    void PerformAction(IUndoableActionaction)
    {
        Actions.Push(action);
        action.Do();
    }
    void Undo()
    {
        var action = Actions.Pop();
        action.Undo();
    }

至于在操作类中存储什么,有些操作可以只存储旧值。但是,一旦我有一个操作来交换电子表格中的两行。我没有将每个单元格的值存储在两行中——我只是存储了行下标,以便它们可以交换回来。如果您为每个操作存储所有状态,那么很容易填满大量内存。

那么你也想要一个重做堆栈,当你撤销一个动作时,它被推到重做堆栈。当执行一个新操作时,重做堆栈需要被清除,这样事情就不会乱了序。

最直接的方法可能是撤销/重做堆栈组合。

另一种方法是使用一个操作数组或列表,只对指向数组中索引的指针进行递增/递减操作。当操作撤消时,索引向后移动一个,当操作重新执行时,索引向前移动一个。这样做的好处是,您不需要每个操作都有一个弹出-然后-推送序列。

注意事项:

  • 如果您多次撤消,然后执行一个操作,所有的必须取消重做操作。
  • 在尝试执行撤销/重做之前,请确保检查边界并确保有可用于撤销/重做的操作。

相关内容

  • 没有找到相关文章

最新更新