前面我們討論過「繼承 CompositeControl 實作 Toolbar 控制項」,本文將繼承 WebControl 來實作同樣功能的 Toolbar 控制項,用不同的方式來實作同一個控制項,進而比較二者之間的差異。
程式碼下載:ASP.NET Server Control - Day16.rar
一、繼承 WebControl 實作 TBToolbar 控制項
step1. 新增繼承 WebControl 的 TBToolbar 控制項
新增繼承 WebControl 的 TBToolbar 控制項,你也可以直接原修改原 TBToolbar 控制項,繼承對象由 CompositeControl 更改為 WebControl即可。跟之前一樣在 TBToolbar 控制項加入 Items 屬性及 Click 事件。
另外 TBToolbar 控制項需實作 INamingContainer 界面,此界面很特殊沒有任何屬性或方法,INamingContainer 界面的作用是子控制項的 ClientID 會在前面加上父控制項的 ClickID,使每個子控制項有唯一的 ClientID。
step2. 建立工具列按鈕集合
覆寫 RenderContents 方法,將原本 TBToolbar (複合控制項) 的 CreateChildControls 方法中建立工具列按鈕程式碼,搬移至 RenderContents 方法即可。
Private Sub ButtonClickEventHandler(ByVal sender As Object, ByVal e As EventArgs)
Dim oButton As Button
Dim oEventArgs As ClickEventArgs
oButton = CType(sender, Button)
oEventArgs = New ClickEventArgs()
oEventArgs.Key = oButton.ID
OnClick(oEventArgs)
End Sub
''' <summary>
''' 覆寫 RenderContents 方法。
''' </summary>
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim oItem As TBToolbarItem
Dim oButton As Button
For Each oItem In Me.Items
oButton = New Button()
oButton.Text = oItem.Text
oButton.Enabled = oItem.Enabled
oButton.ID = oItem.Key
AddHandler oButton.Click, AddressOf ButtonClickEventHandler
Me.Controls.Add(oButton)
Next
If Me.Items.Count = 0 AndAlso Me.DesignMode Then
oButton = New Button()
oButton.Text = "請設定 Items 屬性。"
Me.Controls.Add(oButton)
End If
MyBase.RenderContents(writer)
End Sub
上述的直接搬移過來的程式碼還有個問題,就是原來的使用 AddHandler 來處理按鈕事件的方式變成沒有作用了?因為現在不是複合式控制項,當前端的按鈕 PostBack 傳回伺服端時,TBToolbar 不會事先建立子控制槓,所以機制會找不到原來產生的按鈕,也就無法使用 AddHandler 來處理事件了。
AddHandler oButton.Click, AddressOf ButtonClickEventHandler
step3. 處理 Click 事件
因為不能使用 AddHandler 來處理按鈕事件,所以我們就自行使用 Page.ClientScript.GetPostBackEventReference 方法來產生 PostBack 動作的用戶端指令碼,按鈕的 OnClientClick 去執行 PostBack 的動作。
For Each oItem In Me.Items
oButton = New Button()
oButton.Text = oItem.Text
oButton.Enabled = oItem.Enabled
oButton.ID = oItem.Key
sScript = Me.Page.ClientScript.GetPostBackEventReference(Me, oItem.Key)
oButton.OnClientClick = sScript
Me.Controls.Add(oButton)
Next
TBToolar 控制項輸出的 HTML 碼如下
<span id="TBToolbar1">
<input type="submit" name="TBToolbar1$Add" value="新增" onclick="__doPostBack('TBToolbar1','Add');"
id="TBToolbar1_Add" />
<input type="submit" name="TBToolbar1$Edit" value="修改" onclick="__doPostBack('TBToolbar1','Edit');"
id="TBToolbar1_Edit" />
<input type="submit" name="TBToolbar1$Delete" value="刪除" onclick="__doPostBack('TBToolbar1','Delete');"
id="TBToolbar1_Delete" />
</span>
要自行處理 PostBack 的事件,需實作 IPostBackEventHandler 介面,在 RaisePostBackEvent 方法來引發 TBToolbar 的 Click 事件。
Public Class TBToolbar
Inherits WebControl
Implements INamingContainer
Implements IPostBackEventHandler
Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements
System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
Dim oEventArgs As ClickEventArgs
oEventArgs = New ClickEventArgs()
oEventArgs.Key = eventArgument
Me.OnClick(oEventArgs)
End Sub
End Class
二、測試程式
在測試頁面上放置 TBToolbar 控制項,在 Click 事件撰寫測試程式碼。
備註:本文同步發佈於筆者「ASP.NET 魔法學院」部落格
http://www.dotblogs.com.tw/jeff377/archive/2008/10/17/5706.aspx