2017-02-10 3 views
1

Ich versuche, die Rückgängig machen/Wiederholen-Funktion für die Knoten eines Baumes in C# (TreeView-Komponente) zu implementieren. Ich habe das Memento-Muster verwendet, aber ich habe Probleme mit dem Redo-Teil. Ich kann nicht sehen, wo meine Logik fehlerhaft ist. Hier sind einige Schnappschüsse des CodesUndo/redo Memento-Muster 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; 
    } 

In meiner Form, bevor sie einen Knoten zu löschen ich die SaveMemento() -Methode nenne das ein neues Memento-Objekt erstellt den aktuellen Zustand darstellt. Das Objekt wird zur _mementoStateList hinzugefügt.

Beim Rückgängigmachen und Wiederherstellen einer Aktion rufe ich die obige Undo() und Redo() Methode auf.

Ich gehe davon aus, dass ich die Staaten nicht im richtigen Moment rette? Jede Eingabe wird sehr geschätzt!

+1

Wenn Sie ein neues Memento setzen, sollten Sie Ihre Undo-State-Liste zurücksetzen ... Sonst könnte diese Liste einen sehr seltsamen Inhalt bekommen, bestimmte Anwendungsfälle. – JHBonarius

Antwort

0

Vielleicht sollten Sie implementieren implementieren Rückgängig/wiederholen mit Command Muster, während mit Memento, wenn Sie eine Menge von Staaten speichern müssen (in der Tat die Frage ist, wie viele Aktionen rückgängig machen Sie unterstützen) dann kann die Implementierung schwer sein.

0

Wenn Sie das Memento erstellen, müssen Sie einen tiefen Klon des Objektbaums erstellen, andernfalls wird das Memento nur eine Referenz auf den aktuellen Status sein. In diesem Fall wird sich jede Änderung des Zustands auf alle Erinnerungsstücke auswirken und jeden Versuch zunichte machen, eine Geschichte früherer (oder möglicher zukünftiger) Zustände zu führen.

+0

Ich klopfe tatsächlich das Wurzelelement und speichere es als TreeNode. – MonicaS

+1

Ich denke, tiefes Klonen ist ein Schmerz. Befehlsmuster ist der perfekte Partner des Memento-Musters. – jlvaquero

+0

Das reicht möglicherweise nicht aus, da die Referenzen auf tiefere Knoten vom Wurzelknoten noch auf den aktuellen Zustand zeigen. Wenn Sie nur die Wurzel klonen, ist das höchstens ein oberflächlicher Klon. Für einen tiefen Klon müssen Sie den Baum besuchen und alle Objekte (einschließlich eingerasteter Integer, falls vorhanden) klonen. Die einzige Ausnahme sind Strings, die bei Änderung intrinsisch erstellt werden. – pid