代表确认和退订问题

delegate with confirm and unsubscribe issue

我正在为 delegate/event 苦苦挣扎。我很可能不了解整个情况。 为了论证,我有两种形式:形式1和形式2。

问题:

  1. 如何适当取消订阅事件“frm2.ButtonClicked -= new PassMsg(MsgReceivedFromFrm2);”?
  2. 如果我终止 form 2,我仍然会得到确认 message.why 这是否发生了?

:

 public partial class Form1 : Form
{

    PassMsg NotifyFrm2EventHandler;                             // Delegate definition
    PassMsgWithConfirm NotifyFrm2WithConfirmEventHandler;       // Delegate with return definition
    event PassMsg NotifyFrm2AsEvent;                            // Event definition
    int i;
   
    public Form1()
    {
        InitializeComponent();
        i = 0;
    }

    private void btn_InitializeFrm2_Click(object sender, EventArgs e)
    {
        Form2 frm2 = new Form2();
        NotifyFrm2EventHandler = new PassMsg(frm2.ReceiveMsgFromForm1);                                             // setup link from Form 1 to Form 2
        NotifyFrm2WithConfirmEventHandler = new PassMsgWithConfirm(frm2.ReceiveMsgFromForm1withConfirm);            // setup link from Form 1 to Form 2
        NotifyFrm2AsEvent += new PassMsg(frm2.ReceiveMsgFromForm1);                                                 // setup link from Form 1 to Form 2
        frm2.ButtonClicked += new PassMsg(MsgReceivedFromFrm2);                                                     // setup link from Form 2 to Form 1
        frm2.Show();
    }

    private void btn_Send2Frm2_Click(object sender, EventArgs e)
    {
        i++;

        NotifyFrm2EventHandler?.Invoke("message from form 1 with index " + i.ToString());                                    //  Notification by Call
    }

    private void btn_Send2Frm2WithConfirm_Click(object sender, EventArgs e)
    {
        i++;
        bool confirmed = (bool)(NotifyFrm2WithConfirmEventHandler?.Invoke("message from form 1 with confirm with index" + i.ToString()));             //  Notification by Call
        if (confirmed)
        {
            MessageBox.Show("confirmed.");
        }

    }

    private void btn_sendAsEvent_Click(object sender, EventArgs e)
    {
        i++;
        NotifyFrm2AsEvent?.Invoke("message from form 1 as event with index" + i.ToString());                                //  Notification by Call
    }


    void MsgReceivedFromFrm2(string input)
    {
        label1.Text = input;
    }

}

和form2代码:

    public partial class Form2 : Form
{

    public event PassMsg ButtonClicked;             // Event definition

    public Form2()
    {
        InitializeComponent();
    }

    public void ReceiveMsgFromForm1(string input)
    {
        label1.Text = input;
    }

    public bool ReceiveMsgFromForm1withConfirm(string input)
    {
        label1.Text = input;
        return true;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ButtonClicked("Message from Form 2");
    }
}

引发事件 (Invoke) 的 class(本例中为表单)始终定义事件。调用、触发或引发事件就像广播消息一样。这个class就叫做发布者。因此,在大多数情况下,事件是 public

+= 一起附加到此事件的另一个 class 是订阅者。它是这条消息的接收者。

您以某种方式混淆了发布者和订阅者。

事件类似于自动 属性 但对于委托而言。所以,

public event MessageEventHandler Message;

定义一个事件Message。相当于

private MessageEventHandler _messageEventHandler;
public event MessageEventHandler Message
{
   add 
   { 
       _messageEventHandler += value;
   } 
   remove 
   { 
      _messageEventHandler -= value;
   }
}

因此,您不需要这些明确的事件处理程序字段声明。此外,没有必要使用 new 显式创建委托。 += EventHandlerMethod一个人就好


如果要Form2处理来自Form1的事件,最好将Form1作为构造函数参数传递给Form2Form2 中的事件处理程序可以是私有的。是否订阅该事件也取决于 Form2。控件定义了许多事件,但作为接收者的表单只订阅了其中的少数事件。

发送方:

public class MessageEventArgs : EventArgs
{
    public string Message { get; set; }
}

public delegate void MessageEventHandler(object sender, MessageEventArgs e);

public partial class Form1 : Form
{
    public event MessageEventHandler Message;

    ... constructor and other stuff not shown here.

    private void btnInitializeFrm2_Click(object sender, EventArgs e)
    {
        Form2 frm2 = new Form2(this);
        frm2.Show();
    }

    private void btnSendMessage_Click(object sender, EventArgs e)
    {
        // You don't care who is receiver. You might have many receivers or none.
        OnMessage($"Message from form 1 with index {i}");
    }

    private virtual void OnMessage(string message)
    {
        Message?.Invoke(new MessageEventArgs { Message = message });
    }
}

订阅者:

public partial class Form2 : Form
{
    private Form1 _form1;

    public Form2(Form1 form1)
    {
        InitializeComponent();
        _form1 = form1;
        form1.Message += Form1_Message;
    }

    private void Form1_Message(object sender, MessageEventArgs e)
    {
        MessageBox.Show("Form2 got message: " + e.Message);
    }

    private void btnUnsubscribe_Click(object sender, EventArgs e)
    {
        _form1.Message -= Form1_Message;
    }
}

另见