Ich habe versucht, Command Pattern zum Implementieren von Undo und Redo in meinem Projekt zu verwenden
public abstract class Command
{
protected Form Receiver { set; get; }
protected HtmlElement Element { set; get; }
abstract public void ReDo();
abstract public void UnDo();
public Command(Form receiver)
{
this.Receiver = receiver;
}
}
class AddElementCmd : Command
{
public AddElementCmd(HtmlElement elem, Form receiver)
: base(receiver)
{
Element = elem;
}
public override void ReDo()
{
((FormEdit)Receiver).AddElement(Element,false);
}
public override void UnDo()
{
((FormEdit)Receiver).DelElement(Element, false);
}
}
class DelElementCmd : Command
{
public DelElementCmd(HtmlElement elem, Form receiver)
: base(receiver)
{
Element = elem;
}
public override void ReDo()
{
((FormEdit)Receiver).DelElement(Element, false);
}
public override void UnDo()
{
((FormEdit)Receiver).AddElement(Element, false);
}
}
Implementierung des AddElement
Befehls in FormEdit
.
public void AddElement(HtmlElement elem, bool isNew = true)
{
IHTMLElement2 dom = elem.DomElement as IHTMLElement2;
if (isNew)
{
Command cmd = new AddElementCmd(elem, this);
Undo.Push(cmd);
Redo.Clear();
}
// some codes here....
if (showAlltoolStripButton.Checked)
{
dom.runtimeStyle.visibility = "hidden";
}
else if (showSelectionToolStripButton.Checked)
{
dom.runtimeStyle.visibility = "visible";
}
}
...
Die Stapel Undo
und Redo
werden in der FormMain
Klasse gespeichert und an das Editorformular übergeben.
public Stack<Command> Undo = new Stack<Command>();
public Stack<Command> Redo = new Stack<Command>();
....
FormEdit editor = new FormEdit ();
editor.Browser = webBrowser1;
editor.addedElements = addedElements;
editor.restoreElements = restoreElements;
editor.Undo = Undo;
editor.Redo = Redo;
Wenn FormEdit
der Benutzer in einem neuen Modus auf die Schaltfläche Wiederherstellen oder Rückgängig klickt, wird die entsprechende Funktion in FormEdit
ausgeführt. Wenn ich diesen Empfänger des Befehls überprüft habe, ist dies die Form, in der der Befehl zuerst erstellt wurde und jetzt möglicherweise entsorgt wurde. Ich erwarte, dass das Programm einen Fehler auslöst, aber es scheint, dass das Command
Objekt einen Verweis auf die alte Form speichert und dies zu Fehlverhalten führt.
Daher denke ich, dass ich einen konsistenten Empfänger für die Befehle finden muss, entweder das Hauptformular oder das webBrowser-Steuerelement, das die gleiche Lebensdauer wie die Befehle selbst hat. Trotzdem sollte ich Zugriff auf einige Steuerelemente haben, die sich auf die Befehle beziehen.
Wo kann man die Befehlsfunktionen als Empfänger von Command
Objekten am besten implementieren ? Oder eine andere Möglichkeit, das neue Formular einem vom Stapel abgelegten Befehl zuzuordnen.
Receiver
von jedem Befehlsobjekt festzulegen , ich werde dies tun.