1. 程式人生 > >C#自定義控制元件-事件-委託

C#自定義控制元件-事件-委託

在元件程式設計中對事件的理解是十分重要的,C# 中的“事件”是當物件發生某些有趣的事情時,類向該類的客戶提供通知的一種方法。與事件聯絡最為緊密的,個人認為是委託.委託可以將方法引用封裝在委託物件內。為了弄清元件-事件-委託三者的關係,本人用實際的例子來談談自己的理解。

理解C#程式設計中的元件-事件-委託

    首先建立一個Windows控制元件專案,新增如下控制元件樣板:

    當事件觸發時,會傳遞一個EventArgs型別的引數給事件處理方法,為了能傳遞自定義的資訊,我們可以建立一個繼承於EventArgs的事件引數類,其定義如下:

  1. publicclass EventLoginArgs:System.EventArgs
  2. {
  3. publicstring strUserID;
  4. publicstring strUserName;
  5. publicstring strUserPWD;
  6. publicbool 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. publicdelegatevoid UserLoginEventHandler(
  2. object sender,EventLoginArgs e);
  3. publicdelegatevoid CancelEventHandler(
  4. object sender,EventArgs e);

    在元件中為了能讓使用者自定義某事件的處理方法,所以元件必需提供事件介面.如果只是繼承於單個已有的Windows控制元件,可以過載已知的方 法進行新增自己的處理,也可以宣告自定義的事件介面.而若元件中包含多個控制元件,應該根據實際需要宣告事件介面,此處本人就兩個按鈕的 使用而宣告兩個自定義的事件介面,如下:

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

    其實SubmitLogin 是UserLoginEventHandler委託的例項,令人費解的是此事件的觸發,傳遞,處理過程如何呢?

    在本例中是通過確定按鈕來觸發submitLogin事件的:

  1. privatevoid 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. privatevoid 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 isin test form!
  2. thisis the process in DB
  3. thisis 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. publicdelegatevoid UserLoginEventHandler(
  2. object sender,EventLoginArgs e);
  3. publicdelegatevoid CancelEventHandler(
  4. object sender,EventArgs e);
  5. publicevent UserLoginEventHandler SubmitLogin;
  6. publicevent CancelEventHandler Cancel;
  7. protectedvirtualvoid OnSubmitLogin(EventLoginArgs e)
  8. {
  9. if(this.SubmitLogin!=null)
  10. {
  11. SubmitLogin(this,e);
  12. }
  13. }
  14. protectedvirtualvoid OnCancel(EventArgs e)
  15. {
  16. if(this.Cancel!=null)
  17. Cancel(this,e);
  18. }
  19. publicstring Server
  20. {
  21. }
  22. publicstring DataBase
  23. {
  24. }
  25. publicstring TableSet
  26. {
  27. }
  28. publicstring UserForDB
  29. {
  30. }
  31. publicstring PWDForDB
  32. {
  33. }
  34. publicbool 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. returnfalse;
  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. privatevoid 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. privatevoid btnCancel_Click(
  113. object sender, System.EventArgs e)
  114. {
  115. OnCancel(e);
  116. }
  117. privatevoid UserControl_Load(
  118. object sender, System.EventArgs e)
  119. {
  120. intLoginTime = 0;
  121. }
  122. }
  123. publicclass EventLoginArgs:System.EventArgs
  124. {
  125. publicstring strUserID;
  126. publicstring strUserName;
  127. publicstring strUserPWD;
  128. publicbool bVaild;
  129. public EventLoginArgs(
  130. string userID,string userName,string userPWD)
  131. {
  132. strUserID = userID;
  133. strUserName = userName;
  134. strUserPWD = userPWD;
  135. }
  136. }

    它的客戶程式主要如下:

  1. privatevoid 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. privatevoid 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,可參考擴充套件例子二。