C#自定义控件-事件-委托

转载 2013年12月02日 23:01:17
在组件编程中对事件的理解是十分重要的,C# 中的“事件”是当对象发生某些有趣的事情时,类向该类的客户提供通知的一种方法。与事件联系最为紧密的,个人认为是委托.委托可以将方法引用封装在委托对象内。为了弄清组件-事件-委托三者的关系,本人用实际的例子来谈谈自己的理解。

理解C#编程中的组件-事件-委托

    首先创建一个Windows控件项目,添加如下控件样板:

    当事件触发时,会传递一个EventArgs类型的参数给事件处理方法,为了能传递自定义的信息,我们可以创建一个继承于EventArgs的事件参数类,其定义如下:

  1. public class EventLoginArgs:System.EventArgs
  2. {
  3. public string strUserID;
  4. public string strUserName;
  5. public string strUserPWD;
  6. public bool bVaild;
  7. public EventLoginArgs(
  8. string userID,string userName,string userPWD)
  9. {
  10. strUserID = userID;
  11. strUserName = userName;
  12. strUserPWD = userPWD;
  13. }

    再声明两个委托,它们是对EventLoginArgs和EventArgs对象中的信息的封装,如下:

  1. public delegate void UserLoginEventHandler(
  2. object sender,EventLoginArgs e);
  3. public delegate void CancelEventHandler(
  4. object sender,EventArgs e);

    在组件中为了能让用户自定义某事件的处理方法,所以组件必需提供事件接口.如果只是继承于单个已有的Windows控件,可以重载已知的方 法进行添加自己的处理,也可以声明自定义的事件接口.而若组件中包含多个控件,应该根据实际需要声明事件接口,此处本人就两个按钮的 使用而声明两个自定义的事件接口,如下:

  1. public event UserLoginEventHandler SubmitLogin;
  2. public event CancelEventHandler Cancel;
  3. protected virtual void OnSubmitLogin(EventLoginArgs e)
  4. {
  5. if(this.SubmitLogin!=null)
  6. {
  7. SubmitLogin(this,e);
  8. }
  9. }
  10. protected virtual void OnCancel(EventArgs e)
  11. {
  12. if(this.Cancel!=null)
  13. {
  14. Cancel(this,e);
  15. }

    其实SubmitLogin 是UserLoginEventHandler委托的实例,令人费解的是此事件的触发,传递,处理过程如何呢?

    在本例中是通过确定按钮来触发submitLogin事件的:

  1. private void btnOK_Click(object sender, System.EventArgs e)
  2. {
  3. if(txtID.Text != ""&&txtName.Text !=""&&txtPWD.Text !="")
  4. {
  5. intLoginTime++;
  6. OnSubmitLogin(new EventLoginArgs(
  7. txtID.Text,txtName.Text,txtPWD.Text));
  8. bLogin = TestUserInDB(new EventLoginArgs(
  9. txtID.Text,txtName.Text,txtPWD.Text));
  10. MessageBox.Show(
  11. "this is the btnOK_click function!"
  12. "In control",MessageBoxButtons.OK);
  13. if(!bLogin)
  14. MessageBox.Show(
  15. "Login in Failed!""Login Error"
  16. MessageBoxButtons.OK);
  17. }
  18. else
  19. {
  20. MessageBox.Show(
  21. "Your must input all the items!""Login Info"
  22. MessageBoxButtons.OK);
  23. }
  24. }

    注意本例中的对话框是为了帮助了解事件的过程,真正有用的是第二个例子。

    在btnOK_Click事件响应中,先对进行简单的有效性检查,建议实际工作应作加强完善.intLoginTime变量是尝试登录的次数.TestUserInDB是 通过已知信息在数据库中搜索出有关记录进行判断用户是否合法. 因为组件的测试是通过客户程序的,所以应该创建一个最简单明了的客户 程序.这是一个Windows应用程序,将编译好的组件添加到用户控件栏中,拖出到工作区中,添加SubmitLogin事件的响应程序,如下:

  1. private void userControl1_SubmitLogin(
  2. object sender, Userlogin.EventLoginArgs e)
  3. {
  4. MessageBox.Show("This is in test form!"+
  5. userControl1.bLogin +
  6. "\ns Login times is "+userControl1.intLoginTime +
  7. "\ne's strUserID="+e.strUserID,"Test",
  8. MessageBoxButtons.OK);
  9. }

  此时运行客户程序可得以下结果:

  1. This is in test form!
  2. this is the process in DB
  3. this is the btnOK_click function!

    结果表明单击btnOK按钮时执行组件中的OnSubmitLogin(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)),此方法又调用 SubmitLogin(this,e),从而激发SubmitLogin事件,userControl1_SubmitLogin就进行响应,故打印第一行。

    跟着是执行TestUserInDB,它打印出第二行。

    最后是返回到btnOK_Click中输出最后一行。

C#编程中的组件-事件-委托:例子二

    注意若btnOK_Click中的OnSubmitLogin和TestUserInDB所在的行调换位置,其结果是不同的.第二个例子中,二者的位置调换,先进行数据库 查询判断,再在SubmitLogin的事件响应userControl1_SubmitLogin中处理结果,下面的是例子二的主要代码:

  1. public delegate void UserLoginEventHandler(
  2. object sender,EventLoginArgs e);
  3. public delegate void CancelEventHandler(
  4. object sender,EventArgs e);
  5. public event UserLoginEventHandler SubmitLogin;
  6. public event CancelEventHandler Cancel;
  7. protected virtual void OnSubmitLogin(EventLoginArgs e)
  8. {
  9. if(this.SubmitLogin!=null)
  10. {
  11. SubmitLogin(this,e);
  12. }
  13. }
  14. protected virtual void OnCancel(EventArgs e)
  15. {
  16. if(this.Cancel!=null)
  17. Cancel(this,e);
  18. }
  19. public string Server
  20. {
  21. }
  22. public string DataBase
  23. {
  24. }
  25. public string TableSet
  26. {
  27. }
  28. public string UserForDB
  29. {
  30. }
  31. public string PWDForDB
  32. {
  33. }
  34. public bool TestUserInDB(EventLoginArgs e)
  35. {
  36. //MessageBox.Show(
  37. //"this is the process for DB!",
  38. //"TestUserInDB",MessageBoxButtons.OK);
  39. bool bOK = false;
  40. if(this.strDataBase!=null &&
  41. this.strServer!=null &&
  42. this.strUserForDB!=null)
  43. {
  44. if(this.strPWDForDB==null)
  45. this.strPWDForDB = "";
  46. string strConnection = "server="+this.strServer +
  47. ";database="+this.strDataBase +";UID="+this.strUserForDB +
  48. ";PWD="+this.strPWDForDB;
  49. string strSQL = "select UserID,UserName,UserPWD from "+
  50. this.strTableSet+" where UserID='"+e.strUserID+
  51. "' and UserName='"+e.strUserName +
  52. "' and UserPWD='"+e.strUserPWD+"'";
  53. SqlConnection conn = new SqlConnection(strConnection);
  54. try
  55. {
  56. conn.Open();
  57. }
  58. catch(SqlException ex)
  59. {
  60. MessageBox.Show(
  61. "数据库不能打开!请检查有关参数."
  62. "Error",MessageBoxButtons.OK);
  63. return false;
  64. }
  65. SqlDataAdapter da = new SqlDataAdapter(strSQL,conn);
  66. DataSet ds = new DataSet();
  67. try
  68. {
  69. da.Fill(ds,this.strTableSet);
  70. }
  71. catch(SqlException ex)
  72. {
  73. ......
  74. }
  75. foreach(DataRow row in ds.Tables[this.strTableSet].Rows)
  76. {
  77. if(row != null)
  78. {
  79. bOK = true;
  80. }
  81. }
  82. .......
  83. }
  84. else
  85. {
  86. bOK = false;
  87. }
  88. return bOK;
  89. }
  90. private void btnOK_Click(object sender, System.EventArgs e)
  91. {
  92. if(txtID.Text != ""&&txtName.Text !=""&&txtPWD.Text !="")
  93. {
  94. intLoginTime++;
  95. bLogin = TestUserInDB(new EventLoginArgs(
  96. txtID.Text,txtName.Text,txtPWD.Text));
  97. if(!bLogin)
  98. MessageBox.Show(
  99. "Login in Failed!""Login Error"
  100. MessageBoxButtons.OK);
  101. else
  102. OnSubmitLogin(new EventLoginArgs(
  103. txtID.Text,txtName.Text,txtPWD.Text));
  104. }
  105. else
  106. {
  107. MessageBox.Show(
  108. "Your must input all the items!"
  109. "Login Info",MessageBoxButtons.OK);
  110. }
  111. }
  112. private void btnCancel_Click(
  113. object sender, System.EventArgs e)
  114. {
  115. OnCancel(e);
  116. }
  117. private void UserControl_Load(
  118. object sender, System.EventArgs e)
  119. {
  120. intLoginTime = 0;
  121. }
  122. }
  123. public class EventLoginArgs:System.EventArgs
  124. {
  125. public string strUserID;
  126. public string strUserName;
  127. public string strUserPWD;
  128. public bool bVaild;
  129. public EventLoginArgs(
  130. string userID,string userName,string userPWD)
  131. {
  132. strUserID = userID;
  133. strUserName = userName;
  134. strUserPWD = userPWD;
  135. }
  136. }

    它的客户程序主要如下:

  1. private void userControl1_SubmitLogin(
  2. object sender, Userlogin.EventLoginArgs e)
  3. {
  4.  MessageBox.Show(
  5. "This result is bLogin="+ userControl1.bLogin +
  6. " At "+userControl1.intLoginTime +" times \n UserID="+e.strUserID+
  7. "\n UserName="+e.strUserName,"TestResult",MessageBoxButtons.OK);
  8. }
  9. private void Form1_Load(object sender, System.EventArgs e)
  10. {
  11.  userControl1.Server = "localhost";
  12.  userControl1.DataBase="weiwen";
  13.  userControl1.TableSet = "TestUser";
  14.  userControl1.UserForDB="sa";
  15.  userControl1.PWDForDB = "sa";
  16. }

    以上就对C#编程中的组件-事件-委托做出了一些介绍。读者可以参考学习,也可直接使用此组件,但使用时应当以Microsoft SQL Server 作为后台数据库,所用到的用户表格应有 UserID,UserName,UserPWD三列,同时在客户程序中应对有关参数初始化,SubmitLogin事件返回值是尝试次数intLoginTime和验证是否成功bLogin,可参考扩展例子二。

c# 自定义事件和委托

在windows 编程中用到最多的就是控件的时间了,微软给我们很好的方式,把注意力放到事件执行方法的设计和编码上,但是但我们真正弄懂了事件的真正出发执行原理的话,对我们的编程的提高真是非常榜的,例如在...
  • GoodShot
  • GoodShot
  • 2015年03月05日 10:47
  • 1151

C# 委托实例(跨窗体操作控件)

今天研究了一下,在C#里面却是可以不用自定义消息这么复杂的方法来实现跨窗体调用控件,C#有更好的办法就是委托。 效果描述:有两个窗体,FORM1(一个名为“打开form2”的button控件)和FO...
  • bdstjk
  • bdstjk
  • 2011年11月23日 14:33
  • 22428

c#一个简单的线程实例 委托控制控件

  • 2015年07月12日 10:42
  • 49KB
  • 下载

C#使用委托调用主线程上的控件

摘自其他人博客,自己试过确实解决问题。(如在自己定义的线程里面给textbox赋值) 由于Windows窗体控件本质上不是线程安全的。因此如果有两个或多个线程适度操作某一控件的状态(set valu...
  • wyvbboy
  • wyvbboy
  • 2016年01月26日 15:23
  • 4033

C#线程中使用委托方式设置控件属性

在线程中想要使用label控件根据运行情况显示一些提示,直接使用label.Text="Ok"不行。需要使用委托方式来进行属性的设置。如下:1,声明一个委托      public delegate ...
  • lujunql
  • lujunql
  • 2009年06月19日 16:17
  • 1892

C#自定义类中操作主窗体控件,通过委托实现

主窗体中包含一个标签label1和一个按钮button1 代码如下: public void ChangeLabel(string text) { label1.Text = tex...
  • u011229962
  • u011229962
  • 2015年04月03日 17:34
  • 1788

C# 委托实现跨线程更新控件

public delegate void SetTextHandler(int result);         private void SetCalResult(int result) ...
  • redredredlu
  • redredredlu
  • 2015年04月14日 09:25
  • 423

MFC edit控件实现自动换行

必须设置Vertical Scrollbar = TRUE 必须设置MultiLine = TRUE 必须设置Horizontal Scrollbar = FALSE 必须设置Auto HScr...
  • a200638012
  • a200638012
  • 2016年07月08日 17:22
  • 4778

设置MFC Edit control可以换行显示

MFC Edit control可以换行显示 1.设置edit control 属性Multiline为true 2.写入数据时,想换行的时候写入"\r\n"即可,CString str.Re...
  • a780902723
  • a780902723
  • 2014年12月09日 16:52
  • 2462

MFC中EDIT控件实现换行

一、通过回车换行: 这里要有两个设置 .将控件的属性设置为Mutilines->true; .将控件的另一个属性设置为Want return->true. 水平和垂直滚动条设置...
  • dearwind153
  • dearwind153
  • 2015年12月09日 21:13
  • 3886
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#自定义控件-事件-委托
举报原因:
原因补充:

(最多只允许输入30个字)