2013年2月4日 星期一

[轉]動態產生子控制項的 Event Handler






一般 Calender 都是在 DayRender 事件中依需求加入子控制項,若有個需求要在 Calender 的每日的儲存格中加入一個按鈕,並希望按下這個按鈕能引發該按鈕的 Click 事件,此在事件中撰寫相關程式碼。


以上需求最直覺的方式就是新增一個 Button  加入 Cell 中,並使用 AddHandler 來設定 Click 事件的處理函式,程式碼如下。

 1     Protected Sub Calendar1_DayRender(ByVal sender As ObjectByVal e As System.Web.UI.WebControls.DayRenderEventArgs) 
           Handles
 Calendar1.DayRender 2         Dim oButton As New Button() 3         oButton.Text = "刪除"
 4         AddHandler oButton.Click, AddressOf Button_Click '設定 Button Click 處理函式
 5         e.Cell.Controls.Add(oButton) 6     End Sub
 7 
 8     ''' 

 9     ''' Button Click 事件的處理函式
10     ''' 

11     Private Sub Button_Click(ByVal sender As ObjectByVal e As System.EventArgs)12         '撰寫 Button Click 的程式碼
13     End Sub
可是上面的執行結果會跟你想像的不一樣,當 Button 產生 PostBack 並不會進入指定 Button_Click 方法。 這是為什麼呢?因為在 Calender 的 DayRender 事件動作產生的子控制項並不會被保留,你可以在 Page Load 事件中去查看 Calendar.Controls.Count 會是等於 0。由 PostBack  引發的控制項事件是去依 Request.Form  中資料跟控制項做比較決定是否引發相關事件,而該子控制項根本不存在,更不可能有機會引發它的 Click 事件了。

針對以上的問題,可以利用另一種方式來決定,就是按鈕直接呼叫 __doPostBack() 傳入 __EVENTTARGET 及 __EVENTARGUMENT 引數,然後在伺服端自行處理 PostBack 的回傳。

所以我們改使用 HtmlButton,並在 Attributes("onclick")  直接呼叫 __doPostBack() 函式,其中 __EVENTTARGET 設定為 "CalendarDelete" 做為識別,__EVENTARGUMENT 傳入日期。在 Page Load 時,利用 Me.Request.Form("__EVENTTARGET") 判斷是否由該按鈕產生的 PostBack 並導向 CalendarDelete 方法。

 1     Protected Sub Calendar1_DayRender(ByVal sender As ObjectByVal e As System.Web.UI.WebControls.DayRenderEventArgs) 
           Handles
 Calendar1.DayRender 2         Dim oButton As HtmlButton 3 
 4         oButton = New HtmlButton() 5         oButton.InnerText = "刪除"
 6         oButton.Attributes("onclick"= "__doPostBack('CalendarDelete','" & e.Day.Date.ToShortDateString() & "');"
 7         e.Cell.Controls.Add(oButton) 8     End Sub
 9 
10     Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load11         If Me.Request.Form("__EVENTTARGET"= "CalendarDelete" Then
12             Dim oDate As Date
13             oDate = Date.Parse(Me.Request.Form("__EVENTARGUMENT"))14             CalendarDelete(oDate)15         End If
16 
17     End Sub
18 
19     ''' 

20     ''' Calendar 刪除按鈕的處理方法。
21     ''' 

22     ''' 日期。
23     Private Sub CalendarDelete(ByVal Value As Date)24         '撰寫刪除的相關程式碼
25     End Sub
以上實作的方式,若你會撰寫伺服器控制項的話,甚至可以繼承 Calendar 下來改寫,定義 DayDelete、DayUpdate 或 DayCommand 等事件,在使用上就會更簡便了。這樣做法就如同 GridView 上的 CommandField 會引發 RowCommand 事件的概念是大同小異的。

沒有留言: