Come associo gli oggetti comando al ricevitore giusto?


9

Ho provato a utilizzare il modello di comando per implementare Annulla e Ripeti nel mio progetto

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);
    }
}

Implementazione del AddElementcomando 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";
    }
 }
...

gli stack Undoe Redovengono archiviati nella FormMainclasse e passati al modulo dell'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;

Quando in un nuovo FormEditutente l'utente fa clic sul pulsante Ripeti o Annulla, FormEditviene eseguita la funzione corrispondente in , ma come ho verificato questo ricevitore del comando è la forma in cui il comando è stato creato per la prima volta e ora potrebbe essere stato eliminato. Mi aspetto che il programma generi un errore, ma sembra che l' Commandoggetto memorizzi un riferimento alla vecchia forma e questo porta a comportamenti scorretti.

Pertanto, penso di dover trovare un ricevitore coerente per i comandi, sia nella forma principale che nel controllo webBrowser, che abbia la stessa durata dei comandi stessi. Tuttavia, dovrei avere accesso ad alcuni controlli relativi ai comandi.

Qual è il posto migliore per implementare le funzioni di comando come ricevitore di Commandoggetti? O qualsiasi altro modo per associare il nuovo modulo a un comando estratto dallo stack.


Penso che questa decisione sia tua. Non possiamo aiutarti perché non conosciamo le specifiche o i requisiti funzionali della tua applicazione.
Euforico,

8
Credo che gli oggetti Command debbano contenere solo dati serializzabili (cioè nessun riferimento ad altri oggetti) poiché gli usi comuni per loro includono l'invio dei loro moduli serializzati attraverso le reti, il loro salvataggio in un file per dopo o la loro riproduzione su un altro ricevitore (se si desidera le tue modifiche da mostrare sul mio schermo in tempo reale, ad esempio). Ciò può significare che vuoi passare nel Ricevitore a ciascun metodo di comando, o forse dare ai metodi executeCommand () / undoCommand () del Ricevitore che lo lasciano passare, oppure usare oggetti comando che contengono solo nomi / argomenti del metodo anziché codice .
Ixrec,


@Ixrec Grazie per il tuo consiglio, allora vuoi dire che dovrei essere in grado di impostare l' Receiveroggetto di ciascun comando, lo farò.
Ahmad,

Prendi invece in considerazione l'uso del modello ricordo.
P. Roe,

Risposte:


1

Il modello di comando deve essere applicato al modello e non all'interfaccia utente. Nel tuo caso, fallo

protected HtmlDocument Receiver { set; get; }
protected HtmlElement Element { set; get; }

Per aggiornare l'interfaccia utente, utilizzare il modello Observer , in modo che tutti i moduli aperti e i relativi controlli possano reagire alle modifiche nel modello sottostante.

Il tuo codice diventerà più chiaro e disaccoppiato perché Command può occuparsi solo di modificare il documento e gli osservatori nell'interfaccia utente devono solo aggiornare i controlli indipendentemente da ciò che è cambiato.

Quando un modulo si chiude, verrà annullato la registrazione come osservatore e non verranno mantenuti riferimenti ad esso.

Se un nuovo modulo viene aperto dopo una modifica al documento, verrà notificato dopo un annullamento anche se non era presente al momento della modifica originale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.