Bagaimana cara mengaitkan objek perintah dengan penerima yang tepat?


9

Saya mencoba menggunakan Pola Perintah untuk menerapkan Batalkan dan Kembalikan dalam proyek saya

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

Implementasi AddElementperintah di 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";
    }
 }
...

yang Undodan Redotumpukan disimpan dalam FormMainkelas dan diteruskan ke bentuk redaksi.

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;

Ketika di FormEditpengguna baru mengklik tombol Redo atau Undo, fungsi yang sesuai dalam FormEditdieksekusi, tetapi ketika saya memeriksa penerima perintah ini adalah bentuk di mana perintah pertama kali dibuat dan sekarang mungkin telah dibuang. Saya berharap bahwa program menimbulkan kesalahan, tetapi tampaknya Commandobjek menyimpan referensi ke bentuk lama dan ini mengarah pada perilaku buruk.

Oleh karena itu, saya pikir saya harus menemukan penerima yang konsisten untuk perintah, baik bentuk utama atau kontrol webBrowser, yang memiliki waktu hidup yang sama dengan perintah itu sendiri. Namun saya harus memiliki akses ke beberapa kontrol yang terkait dengan perintah.

Di mana tempat terbaik untuk mengimplementasikan fungsi perintah sebagai penerima Commandobjek? Atau cara lain untuk mengaitkan formulir baru ke perintah yang muncul dari tumpukan.


Saya pikir keputusan ini ada pada Anda. Kami tidak dapat membantu Anda karena kami tidak tahu spesifikasi atau persyaratan fungsional aplikasi Anda.
Euforia

8
Saya percaya objek Command hanya boleh berisi data serializable (yaitu, tidak ada referensi ke objek lain) karena penggunaan umum untuk mereka termasuk mengirimkan formulir serial mereka di jaringan, menyimpannya ke file untuk nanti, atau memutar ulang mereka pada penerima yang berbeda (jika Anda ingin perubahan Anda untuk muncul di layar saya secara real time, misalnya). Itu mungkin berarti Anda ingin meneruskan Receiver ke setiap metode perintah, atau mungkin memberikan Receiver executeCommand () / undoCommand () metode yang membiarkannya meneruskan sendiri, atau mungkin menggunakan objek perintah yang hanya berisi nama metode / argumen alih-alih kode .
Ixrec


@Irrec Terima kasih atas saran Anda, maka maksud Anda saya harus dapat mengatur Receiversetiap objek perintah, saya akan melakukan ini.
Ahmad

Sebaiknya gunakan pola kenang-kenangan.
P. Roe

Jawaban:


1

The Command Pola harus berlaku untuk model yang , dan tidak UI. Dalam kasus Anda, buatlah

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

Untuk memperbarui UI, gunakan pola Observer , sehingga semua formulir terbuka dan kontrolnya dapat bereaksi terhadap perubahan pada model yang mendasarinya.

Kode Anda akan menjadi lebih jelas dan lebih terpisah karena Command hanya dapat menangani perubahan dokumen, dan pengamat di UI hanya perlu memperbarui kontrol tanpa memperhatikan apa yang berubah.

Ketika suatu formulir ditutup, ia akan membatalkan registrasi sebagai pengamat, dan tidak ada referensi untuk itu disimpan.

Jika formulir baru dibuka setelah perubahan pada dokumen, itu akan diberitahukan setelah membatalkan bahkan jika itu tidak ada ketika perubahan asli dibuat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.