给自定义控件(Web Control)添加事件的几种方法。前两种方法可以不实现IPostBackEventHandler...
生活随笔
收集整理的這篇文章主要介紹了
给自定义控件(Web Control)添加事件的几种方法。前两种方法可以不实现IPostBackEventHandler...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
????寫自定義控件已經好久了,也有幾個用得時間比較長的,但是對于“事件”一直是比較模糊,沒有很詳細的理解。
????
????最近升級分頁控件,由于原來使用的是VB.net(在VB.net里面添加一個事件是比較容易的),現在想改用C#,而原來的方法又寫得比較笨拙,想換一個更簡潔一點的方法,所以不得不重新認識一下事件。看了幾遍《道不遠人深入解析asp.net2.0控件開發》居然沒有看懂,可能是自己太笨了吧。又找到了自定義分頁控件開發?看了幾遍,還是比較迷糊,最后把《自定義分頁控件開發》?里提供的代碼down下來看了一下,終于有點明白了。
????先舉一個簡單的例子吧,我們建立一個復合控件,在CreateChildControls()里面添加兩個控件,一個是Label,一個是LinkButton。我們的目的是要給自定義控件加一個事件,以便可以控制Label的Text屬性。
????1、內部事件。
????這個好像是我起的名稱,就是只在自定義控件的內部相應的事件,使用控件的頁面不用相應相關的事件。具體一點就是要在自定義控件內部,在單擊LinkButton的時候修改Label的值。?? public?class?EventTest?:?WebControl,?INamingContainer??
????{
protected?override?void?CreateChildControls()
????????{
????????????Label?lbl?=?new?Label();
????????????lbl.ID?=?"lbl";
????????????this.Controls.Add(lbl);
????????????this.Controls.Add(new?LiteralControl("<BR>"));
????????????LinkButton?btn?=?new?LinkButton();
????????????btn.ID?=?"btn";
????????????btn.Text?=?"復合控件的事件測試";
????????????this.Controls.Add(btn);
?}
}
protected?override?void?CreateChildControls()
????????{
????????????Label?lbl?=?new?Label();
????????????lbl.ID?=?"lbl";?
????????????this.Controls.Add(lbl);
????????????this.Controls.Add(new?LiteralControl("<BR>"));
????????????LinkButton?btn?=?new?LinkButton();
????????????btn.ID?=?"btn";
????????????btn.Text?=?"復合控件的事件測試";
????????????this.Controls.Add(btn);
????????????//給按鈕添加內部事件????????????
????????????btn.Click?+=?new?EventHandler(btn_Click);
}
?void?btn_Click(object?sender,?EventArgs?e)
????????{
????????????Label?lbl?=?(Label)this.FindControl("lbl");
????????????lbl.Text?+=?"控件內部的事件,hi";
????????}
????再次運行網頁,單擊,我們看到了想要的效果。
????怎么樣簡單吧,但是這種方法很不靈活,如果調用控件的網頁也想相應事件怎么辦呢?
????2、外部事件。
????這回我們要讓自定義控件的外部也能相應事件。這個理論上我們要使用委托,也就是delegate,但是系統已經為我們定義好了一個(EventHandler),我們先用現成的。
????這樣我們就給自定義控件定義了一個事件,重新編譯,我們可以在控件的屬性里面看到這個事件。(如果您沒有看到,說明沒有刷新,可能需要把IDE關閉,再次打開)。
? public?event?EventHandler?myClick
????????{
????????????add?{
????????????????Events.AddHandler(this,?value);
????????????}
????????????remove?{
????????????????Events.RemoveHandler(this,?value);
????????????}
????????}
????我們可以添加外部的響應事件了,雙擊,我們加上幾行代碼。
在使用控件的網頁里填寫的代碼? protected?void?EventTest1_myClick(object?sender,?EventArgs?e)
????????{
????????????Label?lbl?=?(Label)EventTest1.FindControl("lbl");
????????????lbl.Text?+=?"外部的事件,Hello"?;
????????}
????運行,奇怪還是原來的樣子,外部事件并沒有相應,不是加了一個事件嗎?外面的事件怎么沒有被調用呢?這是因為,事件先觸發自定義控件內部的事件,然后再由控件內部發出“命令”,調用外部的事件,那么我們怎樣才能發出這個命令呢?我們需要要添加這個函數。這個也是最讓我費解的地方,可能是對委托不是很了解的原因吧。
? protected?void?TestClick(object?sender,EventArgs?e)
????????{
????????????EventHandler?hd?=?(EventHandler)base.Events[this];
????????????if?(hd?!=?null)
????????????{
????????????????hd(sender,?e);
????????????}
????????}
????在修改一下? btn_Click() 就可以了。 void?btn_Click(object?sender,?EventArgs?e)
????????{
????????????Label?lbl?=?(Label)this.FindControl("lbl");
????????????lbl.Text?+=?"控件內部的事件,hi";
????????????//調用外部事件
????????????TestClick(sender,?e);
????????}
????再次運行,OK。
????(實現了內部和外部的事件相應,但是這時候我們還沒有實現傳說中的接口,這是為什么呢?)
????3、“借用”事件,沒有成功。
????我們再給自定義控件加上幾個<a>標簽,讓<a>也可以提交表單(就是觸發事件),填寫如下代碼。
? protected?override?void?CreateChildControls()
????????{
//省略。。。
this.Controls.Add(new?LiteralControl("<BR><a?id=\"aa\"?href=\"javascript:__doPostBack('EventTest1$btn','')\">aa</a>"));
}
????運行OK。然后我們修改一下:__doPostBack的第二個參數,
? <a?id=\"aa\"?href=\"javascript:__doPostBack('EventTest1$btn','1')\">aa</a>")
????奇怪,再次運行的時候出現了異常,看來不讓這么做呀。
????依賴別人是不行了,必須要實現自定義控件自己的事件了。我們請來 IPostBackEventHandler 幫忙。同時<a>的href修改成
? this.Controls.Add(new?LiteralControl("<BR><a?id=\"a1\"?href=\"javascript:__doPostBack('"+?this.ClientID??+"','1')\">[1]</a>"));
????????????this.Controls.Add(new?LiteralControl(" <a?id=\"a2\"?href=\"javascript:__doPostBack('"?+?this.ClientID?+?"','2')\">[2]</a>"));
????????????this.Controls.Add(new?LiteralControl(" <a?id=\"a3\"?href=\"javascript:__doPostBack('"?+?this.ClientID?+?"','3')\">[3]</a>"));
????????????this.Controls.Add(new?LiteralControl(" <a?id=\"a4\"?href=\"javascript:__doPostBack('"?+?this.ClientID?+?"','4')\">[4]</a>"));
在實現 RaisePostBackEvent 函數?
? public?void?RaisePostBackEvent(string?Index)
????????{
????????????Label?lbl?=?(Label)this.FindControl("lbl");
????????????lbl.Text?+=?"自己的事件:"?+?Index;
????????}
????再次運行,OK。同時我們也得到了<a>傳遞過來的數字(頁號)。
????還有一個IPostBackDataHandler接口,由于暫時沒不需要,所以沒有研究,等用到的時候在研究。
----------------------------------------------------------------------
var?theForm?=?document.forms['form1'];
if?(!theForm)?{
????theForm?=?document.form1;
}
function?__doPostBack(eventTarget,?eventArgument)?{
????if?(!theForm.onsubmit?||?(theForm.onsubmit()?!=?false))?{
????????theForm.__EVENTTARGET.value?=?eventTarget;
????????theForm.__EVENTARGUMENT.value?=?eventArgument;
????????theForm.submit();
????}
}
????如果您打開IE的“查看源文件”,會看到這個js函數,這是怎么來的呢?這個是button的事件帶來的,雖然后面的代碼并不需要button了,但是我比較懶,不想自己輸出這個js函數,所以還是保留了button的事件。
????
????好像還是說的不太清楚。自定義控件的事件已經整理清楚了,我可以修改分頁控件里的代碼了,原來寫的比較混亂。分頁控件的下一個版本(v2.0.0.3)將增加兩個事件,這樣就可以向吳旗娃的分頁控件那樣靈活使用了。
附完整代碼:
namespace?JYK.Controls.Page
{
????[DefaultProperty("Text")]
????[ToolboxData("<{0}:EventTest?runat=server></{0}:EventTest>")]
????public?class?EventTest?:?WebControl?,?INamingContainer,IPostBackEventHandler??
????{
????????public?event?EventHandler?myClick
????????{
????????????add
????????????{
????????????????Events.AddHandler(this,?value);
????????????}
????????????remove
????????????{
????????????????Events.RemoveHandler(this,?value);
????????????}
????????}
????????protected?void?TestClick(object?sender,EventArgs?e)
????????{
????????????EventHandler?hd?=?(EventHandler)base.Events[this];
????????????if?(hd?!=?null)
????????????{
????????????????hd(sender,?e);
????????????}
????????}
????????public?void?RaisePostBackEvent(string?Index)
????????{
????????????Label?lbl?=?(Label)this.FindControl("lbl");
????????????lbl.Text?+=?"自己的事件:"?+?Index;
????????}
????????protected?override?void?CreateChildControls()
????????{
????????????Label?lbl?=?new?Label();
????????????lbl.ID?=?"lbl";
????????????this.Controls.Add(lbl);
????????????this.Controls.Add(new?LiteralControl("<BR>"));
????????????LinkButton?btn?=?new?LinkButton();
????????????btn.ID?=?"btn";
????????????btn.Text?=?"復合控件的事件測試";
????????????this.Controls.Add(btn);
????????????//給按鈕添加內部事件
????????????btn.Click?+=?new?EventHandler(btn_Click);
??????????this.Controls.Add(new?LiteralControl("<BR><a?id=\"aa\"?href=\"javascript:__doPostBack('EventTest1$btn','')\">aa</a>"));
????????????this.Controls.Add(new?LiteralControl("<BR><a?id=\"a1\"?href=\"javascript:__doPostBack('"+?this.ClientID??+"','1')\">[1]</a>"));
????????????this.Controls.Add(new?LiteralControl(" <a?id=\"a2\"?href=\"javascript:__doPostBack('"?+?this.ClientID?+?"','2')\">[2]</a>"));
????????????this.Controls.Add(new?LiteralControl(" <a?id=\"a3\"?href=\"javascript:__doPostBack('"?+?this.ClientID?+?"','3')\">[3]</a>"));
????????????this.Controls.Add(new?LiteralControl(" <a?id=\"a4\"?href=\"javascript:__doPostBack('"?+?this.ClientID?+?"','4')\">[4]</a>"));
????????}
????????/**////?控件內部的事件,由現有的控件的事件觸發
?????????void?btn_Click(object?sender,?EventArgs?e)
????????{
????????????Label?lbl?=?(Label)this.FindControl("lbl");
????????????lbl.Text?+=?"控件內部的事件,hi";
????????????//調用外部事件
????????????TestClick(sender,?e);
????????}
????????protected?override?void?Render(HtmlTextWriter?output)
????????{
????????????if?((base.Site?!=?null)?&&?base.Site.DesignMode)
????????????{
????????????????output.Write("<div?style='TEXT-ALIGN:?center;width:100%'>事件測試</div>");
????????????}
????????????else
????????????{
????????????????//Page_Click();
????????????????//output.Write("<div?id='"?+?this.ClientID?+?"Page'?style='TEXT-ALIGN:?center;width:90%'>");
????????????????base.Render(output);
????????????????//output.Write("</div>");
????????????}
????????}
????}
}
總結
以上是生活随笔為你收集整理的给自定义控件(Web Control)添加事件的几种方法。前两种方法可以不实现IPostBackEventHandler...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]获取Setup文件的运行路径
- 下一篇: 问心无愧