深入理解C#編程中的組件-事件-委托
2024-07-21 02:25:08
供稿:網(wǎng)友
在組件編程中對事件的理解是十分重要的,c# 中的“事件”是當對象發(fā)生某些有趣的事情時,類向該類的客戶提供通知的一種方法。與事件聯(lián)系最為緊密的,個人認為是委托.委托可以將方法引用封裝在委托對象內(nèi)。為了弄清組件-事件-委托三者的關(guān)系,本人用實際的例子來談 談小弟的理解。
首先創(chuàng)建一個windows控件項目,添加如下控件樣板。
當事件觸發(fā)時,會傳遞一個eventargs類型的參數(shù)給事件處理方法,為了能傳遞自定義的信息,我們可以創(chuàng)建一個繼承于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;
}
再聲明兩個委托,它們是對eventloginargs和eventargs對象中的信息的封裝,如下:
public delegate void userlogineventhandler(object sender,eventloginargs e);
public delegate void canceleventhandler(object sender,eventargs e);
在組件中為了能讓用戶自定義某事件的處理方法,所以組件必需提供事件接口.如果只是繼承于單個已有的windows控件,可以重載已知的方 法進行添加自己的處理,也可以聲明自定義的事件接口.而若組件中包含多個控件,應該根據(jù)實際需要聲明事件接口,此處本人就兩個按鈕的 使用而聲明兩個自定義的事件接口,如下:
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);
}
其實submitlogin 是userlogineventhandler委托的實例,令人費解的是此事件的觸發(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);
}
}
注意本例中的對話框是為了幫助了解事件的過程,真正有用的是第二個例子。
在btnok_click事件響應中,先對進行簡單的有效性檢查,建議實際工作應作加強完善.intlogintime變量是嘗試登錄的次數(shù).testuserindb是 通過已知信息在數(shù)據(jù)庫中搜索出有關(guān)記錄進行判斷用戶是否合法. 因為組件的測試是通過客戶程序的,所以應該創(chuàng)建一個最簡單明了的客戶 程序.這是一個windows應用程序,將編譯好的組件添加到用戶控件欄中,拖出到工作區(qū)中,添加submitlogin事件的響應程序,如下:
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);
}
此時運行客戶程序可得以下結(jié)果:
this is in test form!
this is the process in db
this is the btnok_click function!
結(jié)果表明單擊btnok按鈕時執(zhí)行組件中的onsubmitlogin(new eventloginargs(txtid.text,txtname.text,txtpwd.text)),此方法又調(diào)用 submitlogin(this,e),從而激發(fā)submitlogin事件,usercontrol1_submitlogin就進行響應,故打印第一行。
跟著是執(zhí)行testuserindb,它打印出第二行。
最后是返回到btnok_click中輸出最后一行。
注意若btnok_click中的onsubmitlogin和testuserindb所在的行調(diào)換位置,其結(jié)果是不同的.第二個例子中,二者的位置調(diào)換,先進行數(shù)據(jù)庫 查詢判斷,再在submitlogin的事件響應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ù)庫不能打開!請檢查有關(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";
}
這兩個例子的完整代碼可以點擊這里下載.
讀者可以參考學習,也可直接使用此組件,但使用時應當以microsoft sql server 作為后臺數(shù)據(jù)庫,所用到的用戶表格應有 userid,username,userpwd三列,同時在客戶程序中應對有關(guān)參數(shù)初始化,submitlogin事件返回值是嘗試次數(shù)intlogintime和驗證是否成功blogin,可參考擴展例子二。
菜鳥學堂: