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 AddElement
perintah 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 Undo
dan Redo
tumpukan disimpan dalam FormMain
kelas 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 FormEdit
pengguna baru mengklik tombol Redo atau Undo, fungsi yang sesuai dalam FormEdit
dieksekusi, 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 Command
objek 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 Command
objek? Atau cara lain untuk mengaitkan formulir baru ke perintah yang muncul dari tumpukan.
sumber
Receiver
setiap objek perintah, saya akan melakukan ini.Jawaban:
The Command Pola harus berlaku untuk model yang , dan tidak UI. Dalam kasus Anda, buatlah
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.
sumber