ฉันจะเชื่อมโยงวัตถุคำสั่งกับผู้รับที่ถูกต้องได้อย่างไร


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

การดำเนินการตามคำสั่งในAddElementFormEdit

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วัตถุจะเก็บการอ้างอิงถึงรูปแบบเก่าและสิ่งนี้นำไปสู่การประพฤติมิชอบ

ดังนั้นฉันคิดว่าฉันต้องค้นหาผู้รับที่สอดคล้องกันสำหรับคำสั่งไม่ว่าจะเป็นรูปแบบหลักหรือการควบคุมเว็บเบราเซอร์ซึ่งมีเวลาชีวิตเช่นเดียวกับคำสั่งของตัวเอง แต่ถึงกระนั้นฉันควรจะสามารถเข้าถึงการควบคุมบางอย่างที่เกี่ยวข้องกับคำสั่ง

สถานที่ที่ดีที่สุดในการใช้ฟังก์ชั่นคำสั่งเป็นผู้รับCommandวัตถุคืออะไร? หรือวิธีอื่นใดในการเชื่อมโยงแบบฟอร์มใหม่กับคำสั่งที่เปิดจากสแต็ก


ฉันคิดว่าการตัดสินใจนี้ขึ้นอยู่กับคุณ เราไม่สามารถช่วยคุณได้เพราะเราไม่ทราบคุณสมบัติหรือข้อกำหนดการใช้งานของแอปพลิเคชันของคุณ
ร่าเริง

8
ฉันเชื่อว่าอ็อบเจกต์ Command ควรมีข้อมูลที่สามารถทำให้เป็นอนุกรมได้ (เช่นไม่มีการอ้างอิงไปยังออบเจกต์อื่น) เนื่องจากการใช้งานทั่วไปสำหรับพวกเขานั้นรวมถึงการส่งแบบฟอร์มที่เป็นอนุกรมของพวกเขาผ่านเครือข่ายบันทึกไว้ในไฟล์ การเปลี่ยนแปลงของคุณเพื่อแสดงบนหน้าจอของฉันในเวลาจริงเป็นต้น) นั่นอาจหมายความว่าคุณต้องการส่งผ่านตัวรับไปยังแต่ละวิธีคำสั่งหรืออาจให้วิธีการเรียกใช้ executeCommand () / undoCommand () วิธีการที่ให้มันผ่านตัวเองหรืออาจใช้วัตถุคำสั่งที่มีเพียงชื่อ / อาร์กิวเมนต์แทนรหัส .
Ixrec

ตัวอย่างการดำเนินงาน และการอภิปราย SO
Radarbob

@Ixrec ขอบคุณสำหรับคำแนะนำของคุณแล้วคุณหมายความว่าฉันควรจะสามารถตั้งค่าReceiverของแต่ละวัตถุคำสั่งฉันจะทำเช่นนี้
Ahmad

พิจารณาใช้รูปแบบของที่ระลึกแทน
P. Roe

คำตอบ:


1

คำสั่งรูปแบบที่ควรนำไปใช้กับรูปแบบและไม่ UI ในกรณีของคุณทำ

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

ในการอัปเดต UI ให้ใช้รูปแบบการสังเกตการณ์ดังนั้นรูปแบบที่เปิดอยู่ทั้งหมดและการควบคุมสามารถตอบสนองต่อการเปลี่ยนแปลงในรูปแบบพื้นฐาน

รหัสของคุณจะชัดเจนและ decoupled มากขึ้นเนื่องจากคำสั่งสามารถดูแลการเปลี่ยนแปลงเอกสารเท่านั้นและผู้สังเกตการณ์ใน UI จะต้องอัปเดตการควบคุมโดยไม่คำนึงถึงสิ่งที่เปลี่ยนแปลงไป

เมื่อปิดฟอร์มมันจะยกเลิกการลงทะเบียนตัวเองในฐานะผู้สังเกตการณ์และจะไม่มีการอ้างอิงถึงฟอร์มนั้น

หากมีการเปิดแบบฟอร์มใหม่หลังจากการเปลี่ยนแปลงเอกสารมันจะได้รับแจ้งหลังจากเลิกทำแม้ว่าจะไม่ปรากฏเมื่อมีการเปลี่ยนแปลงดั้งเดิม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.