C# 委托和事件委托
什么是委托?
1、概念
委托(Delegate)类似于 C 或 C++ 中函数的指针。是存有对某个方法的引用的一种引用类型变量。引用委托可在运行时被改变,特别是用于实现事件和回调方法。其来自于System.Delegate 类。
通俗的讲,委托就是让别人来做,当特别是你需要做一个不确定什么时间来操作的时候就特别有用。比如说 ,小孩不确定的肚子饿这件事情,作为父母非常负责的家长并不需要总是来询问他的小孩是否肚子饿了,只要告诉(委托)其小孩在自己肚子饿的时候表达(发出)肚子饿,来提示家长(触发请求)即可。这样就不要家长(主线程)来实时询问(查询)。大大减小了父母工作负担。
委托常用的函数方法:
public object Invoke(Delegate method);
public object Invoke(Delegate method, params object[] args);
2、代码描述委托
public delegate void weituoFunction(string data, bool Cs); //定义委托
weituoFunction _weituoFunction;//实例化委托
//WinForm加载
private void Form_Load(object sender, EventArgs e)
{
//委托添加对应实现的方法
_weituoFunction= new weituoFunction(RichTextboxAddDsiplay);
}
//定义的事件入口
private void OnPowerChange(object sender, EventArgs e)
{
hungryShow("Iam hungry!",true);
}
//委托实现的方法操作
private void RichTextboxAddDsiplay(string data, bool Cs)
{
if (Cs)
this.richTextBox_Display.AppendText(data + “\r\n”);//true则显示
}
//委托函数的定义实现,传递参数
public void hungryShow(string data, bool Cs)
{
this.Invoke(_weituoFunction, data, Cs);//运行委托功能
}
我用一个精简的实例,描述了一个委托,看起来有点复杂有点绕,仔细思考还是比较容易理解,和回调的方法大同小异。一个委托也是可以实行多个方法,也可以同时调用多个委托。可以携带参数,也可以不适用参数,例子中就使用了两个不同的参数。
什么是事件委托?
1、概念
事件委托也称之为事件代理(Event Delegation)。 是常用绑定事件的常用技巧 ,可以让底层类或方法担当的监听职责,触发自定义的事件。
这里再举个简单的例子,在我们以前小时候,那时候没有这么发达的快递,也没有这么强大的互联网,我就是经常去查看我们楼下的邮箱,每一户都有一个铁箱子。有信寄到的时候邮递员就会放进去,我们不确定里面有没有信件,就经常有事没事去打开看一下。但是很大机会是空空如也,什么也没有,经常让我很是失望。现在就不一样了,什么快递短信消息,什么丰巢快递微信推送消息等等。再也不需要我们自己去查看柜子有没有收到自己的信件或快递了。这些问题都交(委托)给了邮递员或快递柜系统来处理,就好像 我们用户(最高的应用层)交给了邮递方(更底层的传输层),而事件由下至上发送事件。
System.EventHandler类中的public delegate void EventHandler(object sender, EventArgs e),就是专门针对事件委托进行为的方法。
2、代码描述事件委托
class Form1
{
//功能类实例化
Mail _Mail= new Mail();
//加载WinForm框架
private void Form_Load(object sender, EventArgs e)
{
//添加委托事件处理
_Mail.RxChange += OnReceivedChange;
_Mail.RxStart();//启动接收线程
}
//接收改变事件功能方法
private void OnReceivedChange(object sender, EventArgs e)
{
this.richTextBox_Display.AppendText( “您有一个快递!\r\n”);//true则显示
}
}
class Mail
{
public event EventHandler RxChange; //定义事件委托
private void OnDelegateChange(EventArgs eventArgs) //事件委托定义
{
this.RxChange?.Invoke(this, eventArgs);//委托此类的事件功能
}
//启动线程
public void RxStart()
{
ReceiveMailThread = new Thread(new ThreadStart(RxThread));//指定线程函数
ReceiveMailThread.IsBackground = true;//可后台运行
ReceiveMailThread.Name = "接收邮件";//线程名
ReceiveMailThread.Start();//线程开始
}
//接收线程
public void RxThread()
{
try
{
while (true)
{
if(ReceiveMailMonitor()==true)
this.OnDelegateChange(new EventArgs());//使用事件委托
}
}
catch (Exception ex)
{
ex.MessageBox.show(ex.Message,"Err");
}
}
}
class Form1类为主类,class _Mail为分支功能类,注意他们首先必须在同一个工作空间,在_Mail类中委托事件给到 EventHandler RxChange这个定义的委托中, 传递到Form1中去。主程序中有在实例化的对象中添加OnReceivedChange方法(_Mail.RxChange += OnReceivedChange;),从而在_Mail中的委托事件触发到上层OnReceivedChange的工作。一个事件委托也可以执行多个事件或多个添加的方法。ReceiveMailMonitor()是自定义的接收监控,就没有在代码中描述了。
利用事件委托在不同窗体传参
介绍一个很实用的方法,来通过委托传递窗体之间的参数,将子窗口的参数传递给主窗口并显示,这个例子没有使用到invoke,相对比较简单实用。
1、建窗体
我们建立两个窗体,一个主窗体Form1,一个输入子窗体input。
2、主窗体代码:
namespace test
{
// 委托可以声明在命名空间中, 如果声明在类中不是全局,要加前缀引用
public delegate void setTextValue(string textValue);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//按键单击事件
private void button1_Click(object sender, EventArgs e)
{
//实例化输入窗口
input _input = new input();
//初始化事件添加委托的实现方法diaplay,注意不要带参。
_input.setFormTextValue += new setTextValue(diaplay);
//显示输入窗口
_input.ShowDialog();
}
//委托实现的方法,带参数
public void diaplay(string textValue)
{
DISPLAY.Text = textValue;
}
}
3、子窗体代码:
public partial class input : Form
{
public input()
{
InitializeComponent();
}
//声明一个委托类型的事件
public event setTextValue setFormTextValue;
//退出关闭事件
private void input_FormClosing(object sender, FormClosingEventArgs e)
{
//启动事件,获取输入的参数。
setFormTextValue(this.textBox1.Text);
}
}
这个实例完成了从子窗口到主窗口的数据传递,参数可以是一个也可以是多个,可以是不同的数据类型,也包括结构体等。