Traté de usar el Patrón de comando para implementar Deshacer y Rehacer en mi proyecto
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);
}
}
Implementación del AddElement
comando en 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";
}
}
...
Las pilas Undo
y Redo
se almacenan en la FormMain
clase y se pasan al formulario del editor.
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;
Cuando en una nueva, FormEdit
el usuario hace clic en el botón Rehacer o Deshacer, FormEdit
se ejecuta la función correspondiente en el , pero como verifiqué, este receptor del comando es la forma en que el comando se creó por primera vez y ahora se ha eliminado. Espero que el programa genere un error, pero parece que el Command
objeto almacena una referencia a la forma anterior y esto conduce a un mal comportamiento.
Por lo tanto, creo que debo encontrar un receptor consistente para los comandos, ya sea el formulario principal o el control webBrowser, que tiene el mismo tiempo de vida que los comandos en sí. Pero aún así debería tener acceso a algunos controles relacionados con los comandos.
¿Dónde está el mejor lugar para implementar las funciones de comando como receptor de Command
objetos? O cualquier otra forma de asociar el nuevo formulario a un comando emergente de la pila.
fuente
Receiver
de cada objeto de comando, voy a hacer esto.Respuestas:
El patrón de comando debe aplicarse al modelo , y no a la interfaz de usuario. En tu caso, hazlo
Para actualizar la IU, use el patrón Observador , de modo que todos los formularios abiertos y sus controles puedan reaccionar a los cambios en el modelo subyacente.
Su código se volverá más claro y más desacoplado porque Command solo puede encargarse de cambiar el documento, y los observadores en la interfaz de usuario solo tienen que actualizar los controles sin tener en cuenta exactamente qué cambió.
Cuando se cierra un formulario, se anulará su registro como observador y no se mantendrá ninguna referencia a él.
Si se abre un nuevo formulario después de un cambio en el documento, se le notificará después de deshacer, incluso si no estaba presente cuando se realizó el cambio original.
fuente