2017-02-10 108 views
1

我想在C#(treeview组件)中实现树的节点的撤销/重做功能。我已经使用了纪念图案,但是我在重做部分遇到问题。我看不出我的逻辑有瑕疵。下面是删除,我呼吁其创建表示当前状态的新的备忘录对象SaveMemento()方法的一个节点之前的代码撤销/重做纪念图案c#

private List<Memento> _mementoStateList= new List<Memento>(); 
    private List<Memento> _undoStateList= new List<Memento>(); 
    public Memento Memento { get{return null;} 
     set{_mementoStateList.Add(value);} } 

    public Memento Undo() 
    { 
     if (!_mementoStateList.Any()) return null; 
     Memento m = _mementoStateList.Last(); 
     _undoStateList.Add(m); 
     _mementoStateList.Remove(m); 
     return m; 
    } 

    public Memento Redo() 
    { 
     if (!_undoStateList.Any()) return null; 
     Memento m = _undoStateList.Last(); 
     _mementoStateList.Add(m); 
     _undoStateList.Remove(m); 
     return m; 
    } 

在我的形式,一些卡扣。该对象被添加到_mementoStateList。

当撤消和重做动作时,我调用上面的Undo()和Redo()方法。

我假设我没有在正确的时刻保存状态? 任何输入是高度赞赏!

+1

当你设置一个新的纪念品,你应该重置你的撤消状态列表...否则,该列表可能会得到一个非常奇怪的内容是某些用例。 – JHBonarius

回答

0

也许你应该考虑使用Command模式来实现撤销/重做,而如果你需要存储很多状态(实际上问题是你会支持多少撤销操作),那么实现可能很繁重。

0

当您创建纪念品时,您必须对对象树进行深层克隆,否则纪念品将仅仅是对当前状态的引用。在这种情况下,国家的任何改变都会反映在所有纪念品上,破坏任何试图保留先前(或潜在未来)国家的历史。

+0

我确实克隆了根元素并将其存储为TreeNode。 – MonicaS

+1

我认为深度克隆是一种痛苦。命令模式是纪念图案的完美搭档。 – jlvaquero

+0

这可能是不够的,因为从根节点到深层节点的引用仍然指向当前状态。如果你只是克隆根,那最多是一个浅层克隆。对于深层克隆,您必须访问树并在进程中克隆所有对象(如果有的话)(包括盒装整数)。唯一的例外是字符串,它们是根据变化而创建的。 – pid