在窗口形式 C# 中使用委托传递数据订阅和取消订阅

问题描述

我必须使用两个对象(电子邮件、移动设备)的集合传递数据。如果我单击按钮订阅者或取消订阅,如果我单击发布按钮,我输入的值应该被存储并显示到另一个表单。但是,我需要为此任务使用“委托”。

这是我处理输入值的表单

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace Q1
{
    public partial class Form2 : Form
    {

        // declare delegate
        public delegate void PublishMessageDel(ArrayList publist);

        public PublishMessageDel publist = null;

        public void PublishMessage(ArrayList subscribers)
        {
            publist.Invoke(subscribers);
        }

        public Form2()
        {
            InitializeComponent();
            
        }

        private void btnBackToMain_Click(object sender,EventArgs e)
        {
            // back to first form when the buttom is clicked
            this.Hide();
            Form1 mainWindow = new Form1();
            mainWindow.ShowDialog();
            this.Close();
        }

        private void txtEmailTo_Validating(object sender,CancelEventArgs e)
        {
            if (ckbEmailTo.Checked)
            {
                IsEmailFormmatch();
            }
            else if (!ckbEmailTo.Checked)
            {
                btnSubscribe.Enabled = false;
                btnUnsubscribe.Enabled = false;

            }

        }

        private void txtTextTo_Validating(object sender,CancelEventArgs e)
        {
            if (ckbTextTo.Checked)
            {
                IsMobileFormmatch();
            }
            else if (!ckbTextTo.Checked)
            {
                btnSubscribe.Enabled = false;
                btnUnsubscribe.Enabled = false;

            }

        }


        // check valid email and button visibility
        public void IsEmailFormmatch()
        {
            string emailForm = (@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");

            if (!Regex.IsMatch(txtEmailTo.Text,emailForm))
            {
                MessageBox.Show("Invalid Email");
                btnSubscribe.Enabled = false;
                btnUnsubscribe.Enabled = false;
            }
            else
            {
                btnSubscribe.Enabled = true;
                btnUnsubscribe.Enabled = true;
            }
        }

        // check valid mobile and button visibility
        public void IsMobileFormmatch()
        {
            string mobileForm = (@"\d{3}-\d{3}-\d{4}");

            if (!Regex.IsMatch(txtTextTo.Text,mobileForm))
            {
                MessageBox.Show("Invalid Phone Number");
                btnSubscribe.Enabled = false;
                btnUnsubscribe.Enabled = false;
            }
            else
            {
                btnSubscribe.Enabled = true;
                btnUnsubscribe.Enabled = true;
            }
        }

        private void btnSubscribe_Click(object sender,EventArgs e)
        {
            ArrayList subscribers = new ArrayList();

            if (ckbEmailTo.Checked)
            {
                subscribers.Add(txtEmailTo.Text);
            }
            else if (ckbTextTo.Checked)
            {
                subscribers.Add(txtTextTo.Text);                
            }

            foreach (ArrayList list in subscribers)
            {
                PublishMessage(list);
            }
        }

        private void btnUnsubscribe_Click(object sender,EventArgs e)
        {
            ArrayList subscribers = new ArrayList();

            if (ckbEmailTo.Checked)
            {
                subscribers.Remove(txtEmailTo.Text);

            }
            else if (ckbTextTo.Checked)
            {
                subscribers.Remove(txtTextTo.Text);
            }

        }

    }
}

我认为这部分有问题。

private void btnSubscribe_Click(object sender,EventArgs e)
        {
            ArrayList subscribers = new ArrayList();

            if (ckbEmailTo.Checked)
            {
                subscribers.Remove(txtEmailTo.Text);

            }
            else if (ckbTextTo.Checked)
            {
                subscribers.Remove(txtTextTo.Text);
            }

        }

如果我点击发布按钮,这是表单,文本框应该向我显示在前一个表单中订阅的值。

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Q1
{
    public partial class Form3 : Form
    {
        Form2 fm2;
        public Form3()
        {
            InitializeComponent();
            
        }

        private void btnBackToMain3_Click(object sender,EventArgs e)
        {
            this.Hide();
            Form1 mainWindow = new Form1();
            mainWindow.ShowDialog();
            this.Close();
        }

        // change button visibility when the textBox is empty or not
        public void btnPublish_Click(object sender,EventArgs e)
        {
            Form2 fm2 = new Form2();

            var value = fm2.publist += Subscribe;
            txtSubscribers.Text += value;
            //fm2.PublishMessage();

        }

        public void Subscribe(ArrayList list)
        {
            ArrayList subscribers = list;
            txtSubscribers.Text += subscribers.ToString();
        }

        
    }
}

我想我没有正确使用委托并坚持与它链接..

解决方法

这是using delegates microsoft guide
“委托是一种安全封装方法的类型,类似于 C 和 C++ 中的函数指针。与 C 函数指针不同,委托是面向对象的、类型安全和可靠的。委托的类型由名称定义代表。”

因此,在调用 arrSubscribers.Invoke(list); 之前,您应该在 Form3 中创建一个方法,该方法接受您的委托的签名(您将 ArrayList arrSubscribers 作为参数接收)并将引用添加到 {{ 1}}。

public void YourMethod(ArrayList arrSubscribers)
{
// 这里有订阅者的代码
}

fm2.arrSubscribersfm2.arrSubscribers = YourMethod;
示例:

fm2.arrSubscribers += YourMethod;