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 AddElementBefehls 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 Undound Redowerden in der FormMainKlasse 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 FormEditder Benutzer in einem neuen Modus auf die Schaltfläche Wiederherstellen oder Rückgängig klickt, wird die entsprechende Funktion in FormEditausgefü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 CommandObjekt 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 CommandObjekten am besten implementieren ? Oder eine andere Möglichkeit, das neue Formular einem vom Stapel abgelegten Befehl zuzuordnen.
Receivervon jedem Befehlsobjekt festzulegen , ich werde dies tun.