在組件編程中對(duì)事件的理解是十分重要的,C# 中的“事件”是當(dāng)對(duì)象發(fā)生某些有趣的事情時(shí),類向該類的客戶提供通知的一種方法。與事件聯(lián)系最為緊密的,個(gè)人認(rèn)為是委托.委托可以將方法引用封裝在委托對(duì)象內(nèi)。為了弄清組件-事件-委托三者的關(guān)系,本人用實(shí)際的例子來談 談小弟的理解。
首先創(chuàng)建一個(gè)Windows控件項(xiàng)目,添加如下控件樣板。
當(dāng)事件觸發(fā)時(shí),會(huì)傳遞一個(gè)EventArgs類型的參數(shù)給事件處理方法,為了能傳遞自定義的信息,我們可以創(chuàng)建一個(gè)繼承于EventArgs的事件參數(shù) 類,其定義如下:
再聲明兩個(gè)委托,它們是對(duì)EventLoginArgs和EventArgs對(duì)象中的信息的封裝,如下:
在組件中為了能讓用戶自定義某事件的處理方法,所以組件必需提供事件接口.如果只是繼承于單個(gè)已有的Windows控件,可以重載已知的方 法進(jìn)行添加自己的處理,也可以聲明自定義的事件接口.而若組件中包含多個(gè)控件,應(yīng)該根據(jù)實(shí)際需要聲明事件接口,此處本人就兩個(gè)按鈕的 使用而聲明兩個(gè)自定義的事件接口,如下:
其實(shí)SubmitLogin 是UserLoginEventHandler委托的實(shí)例,令人費(fèi)解的是此事件的觸發(fā),傳遞,處理過程如何呢?
在本例中是通過確定按鈕來觸發(fā)submitLogin事件的:
注意本例中的對(duì)話框是為了幫助了解事件的過程,真正有用的是第二個(gè)例子。
在btnOK_Click事件響應(yīng)中,先對(duì)進(jìn)行簡(jiǎn)單的有效性檢查,建議實(shí)際工作應(yīng)作加強(qiáng)完善.intLoginTime變量是嘗試登錄的次數(shù).TestUserInDB是 通過已知信息在數(shù)據(jù)庫中搜索出有關(guān)記錄進(jìn)行判斷用戶是否合法. 因?yàn)榻M件的測(cè)試是通過客戶程序的,所以應(yīng)該創(chuàng)建一個(gè)最簡(jiǎn)單明了的客戶 程序.這是一個(gè)Windows應(yīng)用程序,將編譯好的組件添加到用戶控件欄中,拖出到工作區(qū)中,添加SubmitLogin事件的響應(yīng)程序,如下:
此時(shí)運(yùn)行客戶程序可得以下結(jié)果:
結(jié)果表明單擊btnOK按鈕時(shí)執(zhí)行組件中的OnSubmitLogin(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)),此方法又調(diào)用 SubmitLogin(this,e),從而激發(fā)SubmitLogin事件,userControl1_SubmitLogin就進(jìn)行響應(yīng),故打印第一行。
跟著是執(zhí)行TestUserInDB,它打印出第二行。
最后是返回到btnOK_Click中輸出最后一行。
注意若btnOK_Click中的OnSubmitLogin和TestUserInDB所在的行調(diào)換位置,其結(jié)果是不同的.第二個(gè)例子中,二者的位置調(diào)換,先進(jìn)行數(shù)據(jù)庫 查詢判斷,再在SubmitLogin的事件響應(yīng)userControl1_SubmitLogin中處理結(jié)果,下面的是例子二的主要代碼:
它的客戶程序主要如下:
這兩個(gè)例子的完整代碼可以點(diǎn)擊這里下載.
讀者可以參考學(xué)習(xí),也可直接使用此組件,但使用時(shí)應(yīng)當(dāng)以Microsoft SQL Server 作為后臺(tái)數(shù)據(jù)庫,所用到的用戶表格應(yīng)有 UserID,UserName,UserPWD三列,同時(shí)在客戶程序中應(yīng)對(duì)有關(guān)參數(shù)初始化,SubmitLogin事件返回值是嘗試次數(shù)intLoginTime和驗(yàn)證是否成功bLogin,可參考擴(kuò)展例子二。
首先創(chuàng)建一個(gè)Windows控件項(xiàng)目,添加如下控件樣板。
|
當(dāng)事件觸發(fā)時(shí),會(huì)傳遞一個(gè)EventArgs類型的參數(shù)給事件處理方法,為了能傳遞自定義的信息,我們可以創(chuàng)建一個(gè)繼承于EventArgs的事件參數(shù) 類,其定義如下:
public class EventLoginArgs:System.EventArgs
{ public string strUserID; public string strUserName; public string strUserPWD; public bool bVaild; public EventLoginArgs(string userID,string userName,string userPWD) { strUserID = userID; strUserName = userName; strUserPWD = userPWD; } |
再聲明兩個(gè)委托,它們是對(duì)EventLoginArgs和EventArgs對(duì)象中的信息的封裝,如下:
public delegate void UserLoginEventHandler(object sender,EventLoginArgs e);
public delegate void CancelEventHandler(object sender,EventArgs e); |
在組件中為了能讓用戶自定義某事件的處理方法,所以組件必需提供事件接口.如果只是繼承于單個(gè)已有的Windows控件,可以重載已知的方 法進(jìn)行添加自己的處理,也可以聲明自定義的事件接口.而若組件中包含多個(gè)控件,應(yīng)該根據(jù)實(shí)際需要聲明事件接口,此處本人就兩個(gè)按鈕的 使用而聲明兩個(gè)自定義的事件接口,如下:
public event UserLoginEventHandler SubmitLogin;
public event CancelEventHandler Cancel; protected virtual void OnSubmitLogin(EventLoginArgs e) { if(this.SubmitLogin!=null) { SubmitLogin(this,e); } } protected virtual void OnCancel(EventArgs e) { if(this.Cancel!=null) { Cancel(this,e); } |
其實(shí)SubmitLogin 是UserLoginEventHandler委托的實(shí)例,令人費(fèi)解的是此事件的觸發(fā),傳遞,處理過程如何呢?
在本例中是通過確定按鈕來觸發(fā)submitLogin事件的:
private void btnOK_Click(object sender, System.EventArgs e)
{ if(txtID.Text != ""&&txtName.Text !=""&&txtPWD.Text !="") { intLoginTime++; OnSubmitLogin(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)); bLogin = TestUserInDB(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)); MessageBox.Show("this is the btnOK_click function!","In control",MessageBoxButtons.OK); if(!bLogin) MessageBox.Show("Login in Failed!","Login Error",MessageBoxButtons.OK); } else { MessageBox.Show("Your must input all the items!","Login Info",MessageBoxButtons.OK); } } |
注意本例中的對(duì)話框是為了幫助了解事件的過程,真正有用的是第二個(gè)例子。
在btnOK_Click事件響應(yīng)中,先對(duì)進(jìn)行簡(jiǎn)單的有效性檢查,建議實(shí)際工作應(yīng)作加強(qiáng)完善.intLoginTime變量是嘗試登錄的次數(shù).TestUserInDB是 通過已知信息在數(shù)據(jù)庫中搜索出有關(guān)記錄進(jìn)行判斷用戶是否合法. 因?yàn)榻M件的測(cè)試是通過客戶程序的,所以應(yīng)該創(chuàng)建一個(gè)最簡(jiǎn)單明了的客戶 程序.這是一個(gè)Windows應(yīng)用程序,將編譯好的組件添加到用戶控件欄中,拖出到工作區(qū)中,添加SubmitLogin事件的響應(yīng)程序,如下:
private void userControl1_SubmitLogin(object sender, Userlogin.EventLoginArgs e)
{ MessageBox.Show("This is in test form!"+ userControl1.bLogin +"/ns Login times is "+userControl1.intLoginTime +"/ne's strUserID="+e.strUserID,"Test",MessageBoxButtons.OK); } |
此時(shí)運(yùn)行客戶程序可得以下結(jié)果:
This is in test form!
this is the process in DB this is the btnOK_click function! |
結(jié)果表明單擊btnOK按鈕時(shí)執(zhí)行組件中的OnSubmitLogin(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)),此方法又調(diào)用 SubmitLogin(this,e),從而激發(fā)SubmitLogin事件,userControl1_SubmitLogin就進(jìn)行響應(yīng),故打印第一行。
跟著是執(zhí)行TestUserInDB,它打印出第二行。
最后是返回到btnOK_Click中輸出最后一行。
注意若btnOK_Click中的OnSubmitLogin和TestUserInDB所在的行調(diào)換位置,其結(jié)果是不同的.第二個(gè)例子中,二者的位置調(diào)換,先進(jìn)行數(shù)據(jù)庫 查詢判斷,再在SubmitLogin的事件響應(yīng)userControl1_SubmitLogin中處理結(jié)果,下面的是例子二的主要代碼:
public delegate void UserLoginEventHandler(object sender,EventLoginArgs e);
public delegate void CancelEventHandler(object sender,EventArgs e); public event UserLoginEventHandler SubmitLogin; public event CancelEventHandler Cancel; protected virtual void OnSubmitLogin(EventLoginArgs e) { if(this.SubmitLogin!=null) { SubmitLogin(this,e); } } protected virtual void OnCancel(EventArgs e) { if(this.Cancel!=null) Cancel(this,e); } public string Server { } public string DataBase { } public string TableSet { } public string UserForDB { } public string PWDForDB { } public bool TestUserInDB(EventLoginArgs e) { //MessageBox.Show("this is the process for DB!","TestUserInDB",MessageBoxButtons.OK); bool bOK = false; if(this.strDataBase!=null && this.strServer!=null && this.strUserForDB!=null) { if(this.strPWDForDB==null) this.strPWDForDB = ""; string strConnection = "server="+this.strServer +";database="+this.strDataBase +";UID="+this.strUserForDB +";PWD="+this.strPWDForDB; string strSQL = "select UserID,UserName,UserPWD from "+this.strTableSet+" where UserID='"+e.strUserID+"' and UserName='"+e.strUserName +"' and UserPWD='"+e.strUserPWD+"'"; SqlConnection conn = new SqlConnection(strConnection); try { conn.Open(); } catch(SqlException ex) { MessageBox.Show("數(shù)據(jù)庫不能打開!請(qǐng)檢查有關(guān)參數(shù).","Error",MessageBoxButtons.OK); return false; } SqlDataAdapter da = new SqlDataAdapter(strSQL,conn); DataSet ds = new DataSet(); try { da.Fill(ds,this.strTableSet); } catch(SqlException ex) { ...... } foreach(DataRow row in ds.Tables[this.strTableSet].Rows) { if(row != null) { bOK = true; } } ....... } else { bOK = false; } return bOK; } private void btnOK_Click(object sender, System.EventArgs e) { if(txtID.Text != ""&&txtName.Text !=""&&txtPWD.Text !="") { intLoginTime++; bLogin = TestUserInDB(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)); if(!bLogin) MessageBox.Show("Login in Failed!","Login Error",MessageBoxButtons.OK); else OnSubmitLogin(new EventLoginArgs(txtID.Text,txtName.Text,txtPWD.Text)); } else { MessageBox.Show("Your must input all the items!","Login Info",MessageBoxButtons.OK); } } private void btnCancel_Click(object sender, System.EventArgs e) { OnCancel(e); } private void UserControl_Load(object sender, System.EventArgs e) { intLoginTime = 0; } } public class EventLoginArgs:System.EventArgs { public string strUserID; public string strUserName; public string strUserPWD; public bool bVaild; public EventLoginArgs(string userID,string userName,string userPWD) { strUserID = userID; strUserName = userName; strUserPWD = userPWD; } } |
它的客戶程序主要如下:
private void userControl1_SubmitLogin(object sender, Userlogin.EventLoginArgs e)
{ MessageBox.Show("This result is bLogin="+ userControl1.bLogin +" At "+userControl1.intLoginTime +" times /n UserID="+e.strUserID+"/n UserName="+e.strUserName,"TestResult",MessageBoxButtons.OK); } private void Form1_Load(object sender, System.EventArgs e) { userControl1.Server = "localhost"; userControl1.DataBase="weiwen"; userControl1.TableSet = "TestUser"; userControl1.UserForDB="sa"; userControl1.PWDForDB = "sa"; } |
這兩個(gè)例子的完整代碼可以點(diǎn)擊這里下載.
讀者可以參考學(xué)習(xí),也可直接使用此組件,但使用時(shí)應(yīng)當(dāng)以Microsoft SQL Server 作為后臺(tái)數(shù)據(jù)庫,所用到的用戶表格應(yīng)有 UserID,UserName,UserPWD三列,同時(shí)在客戶程序中應(yīng)對(duì)有關(guān)參數(shù)初始化,SubmitLogin事件返回值是嘗試次數(shù)intLoginTime和驗(yàn)證是否成功bLogin,可參考擴(kuò)展例子二。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
