Як я пов’язую командні об'єкти з правильним приймачем?


9

Я намагався використовувати командний зразок для реалізації 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об'єктів? Або будь-який інший спосіб пов’язати нову форму з командою, що вискочила зі стека.


Я думаю, що це рішення саме на вас. Ми не можемо вам допомогти, оскільки ми не знаємо специфікації та функціональних вимог вашої заявки.
Ейфорія

8
Я вважаю, що об'єкти Command повинні містити дані, які можна серіалізувати (тобто ніяких посилань на інші об’єкти), оскільки загальне використання для них включає надсилання їх серіалізованих форм по мережах, збереження їх у файл для подальшого або повторне відтворення на іншому приймачі (якщо ви хочете наприклад, ваші зміни відображатимуться на моєму екрані). Це може означати, що ви хочете передати в Приймачі кожен метод команд, або, можливо, дати Receiver методам ExecuteCommand () / undoCommand (), які дозволяють йому передавати себе, або, можливо, використовувати об'єкти команд, які містять лише назви методів / аргументів замість коду .
Іксрек


@Ixrec Дякую за пораду, тоді ти маєш на увазі, що я повинен мати можливість встановити Receiverкожен командний об'єкт, я збираюся це зробити.
Ахмад

Поміркуйте замість цього використовувати шаблон пам'яті.
P. Roe

Відповіді:


1

Командна модель повинна застосовуватися до моделі , а не призначений для користувача інтерфейс. У вашому випадку зробіть це

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

Для оновлення інтерфейсу користуйтесь шаблоном Observer , тому всі відкриті форми та їх елементи керування можуть реагувати на зміни основної моделі.

Ваш код стане більш чітким і відокремленим, оскільки Command може подбати лише про зміну документа, а спостерігачам в інтерфейсі потрібно лише оновити елементи керування, не зважаючи на те, що саме змінилося.

Коли форма закриється, вона не зареєструється як спостерігач, і ніяких посилань на неї не зберігатиметься.

Якщо після зміни документа відкриється нова форма, вона буде повідомлена після скасування, навіть якщо вона не була присутня при внесенні оригінальної зміни.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.