2017-02-10 160 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