Próbowałem użyć Wzorca poleceń do implementacji Cofnij i Ponów w moim projekcie
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);
}
}
Realizacja AddElement
polecenia w 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";
}
}
...
Undo
i Redo
stosy są przechowywane w FormMain
klasie i są przekazywane do formularza edytora.
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;
Gdy w nowym FormEdit
użytkownik kliknie przycisk Ponów lub Cofnij, odpowiednia funkcja w FormEdit
jest wykonywana, ale jak sprawdziłem, odbiornik polecenia jest formą, w której polecenie zostało utworzone po raz pierwszy, a teraz mogło zostać usunięte. Oczekuję, że program zgłosi błąd, ale wygląda na to, że Command
obiekt przechowuje odniesienie do starej formy, co prowadzi do złego zachowania.
Dlatego myślę, że muszę znaleźć spójny odbiornik dla poleceń, zarówno głównej, jak i kontrolki webBrowser, która ma taki sam czas życia jak same polecenia. Ale powinienem mieć dostęp do niektórych elementów sterujących związanych z poleceniami.
Gdzie jest najlepsze miejsce na wdrożenie funkcji poleceń jako odbiornika Command
obiektów? Lub w jakikolwiek inny sposób powiązania nowego formularza z poleceniem wyskakującym ze stosu.
źródło
Receiver
każdy obiekt polecenia, zamierzam to zrobić.Odpowiedzi:
Poleceń wzór powinno stosować się do modelu , a nie UI. W twoim przypadku, zrób to
Aby zaktualizować interfejs użytkownika, użyj wzorca obserwatora , aby wszystkie otwarte formularze i ich kontrolki mogły reagować na zmiany w modelu bazowym.
Twój kod stanie się bardziej przejrzysty i oddzielony, ponieważ Command może zająć się tylko zmianą dokumentu, a obserwatorzy w interfejsie użytkownika muszą tylko aktualizować formanty bez względu na to, co się zmieniło.
Kiedy formularz zostanie zamknięty, wyrejestruje się jako obserwator i nie zostaną zachowane żadne odniesienia do niego.
Jeśli nowy formularz zostanie otwarty po zmianie dokumentu, zostanie o nim powiadomiony po cofnięciu, nawet jeśli nie był obecny w momencie dokonania pierwotnej zmiany.
źródło