Я пытался использовать Command Pattern для реализации Undo и Redo в моем проекте
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);
}
}
Реализация AddElement
команды в 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
и Redo
стеки хранятся в FormMain
классе и передаются в виде редактора.
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;
Когда в новом FormEdit
пользователь нажимает кнопку «Вернуть» или «Отменить», соответствующая функция в FormEdit
выполняется, но, как я уже проверял, этот получатель команды является формой, в которой команда была создана впервые и теперь может быть удалена. Я ожидаю, что программа выдаст ошибку, но кажется, что Command
объект хранит ссылку на старую форму, и это приводит к неправильному поведению.
Поэтому я считаю, что должен найти согласованный приемник для команд, либо основной формы, либо элемента управления webBrowser, который имеет то же время жизни, что и сами команды. Но все же у меня должен быть доступ к некоторым элементам управления, связанным с командами.
Где лучшее место для реализации командных функций в качестве приемника Command
объектов? Или любой другой способ связать новую форму с командой, извлеченной из стека.
источник
Receiver
каждый объект команды, я собираюсь сделать это.Ответы:
Командная модель должна применяться к модели , а не пользовательский интерфейс. В вашем случае сделайте это
Чтобы обновить пользовательский интерфейс, используйте шаблон Observer , чтобы все открытые формы и их элементы управления могли реагировать на изменения в базовой модели.
Ваш код станет более четким и разделенным, потому что Command может позаботиться только об изменении документа, а наблюдатели в пользовательском интерфейсе должны только обновлять элементы управления, независимо от того, что именно изменилось.
Когда форма закрывается, она отменяет регистрацию в качестве наблюдателя, и ссылки на нее не сохраняются.
Если новая форма открывается после изменения в документе, она будет уведомлена после отмены, даже если ее не было, когда было сделано первоначальное изменение.
источник