C#事件与委托过程分析
【IT168 技术文档】
简述
在.NET应用程序开发中,有很多定义好的事件,如click,Keydown,Enter等,这些事件就有点类似委托的概念,只不过委托更灵活,可以在不同的界面上传递参数而返回需要的结果值。在C#中,增加了一个新的数据类型,即Delegate(委托),Delegate可以被认为是一种基于Object类的、类型安全的函数指针,它可以定义多个方法。委托处理问题更类似于C++的函数指针和Java语言中的接口,其代码是安全的,可管理的。委托最重要的应用就是定义事件,我们可以使用委托将方法的引用压缩到委托对象中,委托对象能被传递给调用该方法引用的代码,也就是说在事件中向委托传递参数,委托会返回一个具体的值,而不需要把每个方法都写在代码中。
委托是不需要具体知道需要引用哪个类,关键的就是方法的描述类型和引用类型要与委托所匹配,所以在定义事件数据的类时,一般定义Object类(任何类都是继承Object类),当然如果你具体知道使用的类型,可以直接定义string、int……等等。
组成事件的三因素
1.提供事件数据的类——公共使用的类
事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。该类必须从 System.EventArgs(它是事件数据的基类)导出。代码如下:
public class ExportEventArgs: EventArgs
![]()
...{
public object mxnum;
public object Exportmxnum
...{
get...{return mxnum;}
}
public ExportEventArgs(object mxnum)
...{
this.mxnum = mxnum;
}
}
2.事件委托
代码如下:
public delegate void ExportEventHandler(object sender, ExportEventArgs e);
![]()
public event ExportEventHandler Export;//事件的定义
3.引发事件的类或直接定义一个函数引发事件
代码如下:
protected virtual void OnExport(ExportEventArgs e)
![]()
...{
if (Export!= null)
![]()
...{
//Invokes the delegates.
Export (this, e);
}
}
当控件中执行OnExport这个函数时,会触发事件,并将e作为事件的参数。定义函数代码如下:
public void ExportSelect(string mxnum)
![]()
...{
ExportEventArgs ExportArgs = new ExportEventArgs (mxnum);
![]()
// 利用委托来触发事件。通过 ExportEventArgs传递的参数集初始化事件
![]()
// 必须匹配委托ExportEventHandler的签名.
Export (this, ExportArgs);
}
ExportEventArgs是从EventArgs派生的向事件传递参数集的类,在调用引发事件的类或调用ExportEventArgs类时触发事件,传回e参数,从而ExportEventArgs传回数据。
示例:做一个用户控件,在用户控件中生成一个DataSet,访问一个服务器的数据信息,然后在Windosw应用程序中,通过传递一个参数,然后用户控件返回一个dataSet,在DataGrid中显示出来。
新建一个项目,选择类,生成解决方案,然后删除刚才创建的类,添加用户控件UserControl1.cs。然后我们在用户控件类的里面开始定义委托声明,代码如下:
public class ExportEventArgs :EventArgs
![]()
...{
private object mxnum;
public object Exportmxnum
...{
get...{return mxnum;}
}
public ExportEventArgs(object mxnum)
...{
this.mxnum=mxnum;
}
}
public delegate void ExportEventHandler(object sender,ExportEventArgs e);
![]()
public event ExportEventHandler Export;
![]()
//生成一个函数调用委托事件
![]()
public void ExportSelect(object mxnum)
![]()
...{
ExportEventArgs ExArgs=new ExportEventArgs(mxnum);
![]()
Export(this,ExArgs);
}
当然也可以生成OnExport函数,由于还需要在应用程序中定义ExportEventArgs 类,所以直接在函数中定义好。
从数据连接拖过来一个表,生成dataSet1, sqlDataAdapter1.表中有mxnum字段,利用适配器为它设置一个条件@part,为了在接受事件的类中传给mxnum字段一个值,所以我们为用户控件定义了一个属性mxnum。可以修改名字)如图1-1所示。

图1-1:用户控件的属性mxnum
用户控件的属性,为了传回一个@part参数值,代码如下:
private string part;
![]()
public string mxnum
![]()
...{
![]()
get...{return part;}
![]()
set...{part=value;}
![]()
}
这时再拖过来一个button1按钮,在应用程序中我们通过附值mxnum属性传来的part值给sqlDataAdapter1的参数,然后利用ExportSelect把dataSet1调回到ExportEventArgs类中,再传回一个结果。代码如下:
private void button1_Click(object sender, System.EventArgs e)
![]()
...{
![]()
sqlDataAdapter1.SelectCommand.Parameters["@part"].Value=this.part;
![]()
sqlDataAdapter1.Fill(this.dataSet11.BOM);
![]()
ExportSelect(this.dataSet11);
![]()
}
添加一个项目,windows应用程序,添加一个textbox1,在textbox1的textBox1的TextChanged事件中写入:“//向用户控件的mxnum属性附值“。代码如下:
userControl11.mxnum=this.textBox1.Text;
然后把用户控件拖到Windows应用程序中,点击用户控件的事件属性,找到Export事件,向里面写入如下代码:
private void userControl11_Export(object sender, Test1.UserControl1.ExportEventArgs e)
![]()
...{
![]()
DataSet ds=(DataSet)e.Exportmxnum;
![]()
dataGrid1.DataSource=ds.Tables[0].DefaultView;
![]()
//如果知道表名,可以直接写table[“tablename”]
![]()
}
这时,我们通过在textBox1.text中输入一个具体的值,userControl11.mxnum属性就会通过Export事件,传给button1_Click事件一个@part,然后再通过委托返回一个dataSet,这样在DataGrid中就可以把委托的内容显示出来。
作者简介:赵宇;Itpub .NET开发技术版版主;曾开发ERP、SQL Server 2000、Oracle的开发。