随笔 - 103  文章 - 0 评论 - 385 trackbacks - 35

一般 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     ''' <summary>
 9     ''' Button Click 事件的處理函式
10     ''' </summary>
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.Load
11         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     ''' <summary>
20     ''' Calendar 刪除按鈕的處理方法。
21     ''' </summary>
22     ''' <param name="Value">日期。</param>
23     Private Sub CalendarDelete(ByVal Value As Date)
24         '撰寫刪除的相關程式碼
25     End Sub

以上實作的方式,若你會撰寫伺服器控制項的話,甚至可以繼承 Calendar 下來改寫,定義 DayDelete、DayUpdate 或 DayCommand 等事件,在使用上就會更簡便了。這樣做法就如同 GridView 上的 CommandField 會引發 RowCommand 事件的概念是大同小異的。


posted @ 2007-12-14 20:31 jeff377 阅读(838) 评论(1) 编辑
在上一篇「GridView 中的子控制項取得所屬的 GridViewRow 及 RowIndex」 文章中有提到 TemplateField 中的 ChckBox 產生 PostBack 觸發事件,若我們希望直接使用 CheckBoxField 能不能達到相同 PostBack 的效果呢?以下的範例,就是要以 CheckBoxField 來達到相同效果。

假設要執行 PostBack 的 CheckBoxField 置於 GridView 中第二個欄位(欄位索引為1)。

 1         <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID"
 2             DataSourceID="SqlDataSource1" EmptyDataText="沒有資料錄可顯示。">
 3             <Columns>
 4                 <asp:CommandField ShowEditButton="True" />
 5                 <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" />
 6                 <asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID" />
 7                 <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
 8                 <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" />
 9                 <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" />
10             </Columns>
11         </asp:GridView>

我們必須在 GridView 的 RowCreated 事件中,抓取 CheckBoxField 欄位中的 CheckBox 控制項,設定其 AutoPostBack 為 True,並攔截它的 CheckedChanged 事件導向 CheckBox1_CheckedChanged 函式。

 1 Partial Class _Default
 2     Inherits System.Web.UI.Page
 3 
 4     Protected Sub GridView1_RowCreated(ByVal sender As Object,ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
                
Handles GridView1.RowCreated
 5         Dim oCheckBox As CheckBox
 6         If e.Row.RowType = DataControlRowType.DataRow Then
 7             'CheckBoxField 的欄位索引為 1
 8             oCheckBox = CType(e.Row.Cells(1).Controls(0), CheckBox)
 9             oCheckBox.AutoPostBack = True
10             AddHandler oCheckBox.CheckedChanged, AddressOf CheckBox1_CheckedChanged
11         End If
12     End Sub
13 
14     Protected Sub CheckBox1_CheckedChanged(ByVal sender As ObjectByVal e As System.EventArgs)
15         Dim oCheckBox As CheckBox
16         Dim oGridViewRow As GridViewRow
17         Dim iRowIndex As Integer
18 
19         oCheckBox = CType(sender, CheckBox)
20 
21         '取得控制項所屬性 GridViewRow
22         oGridViewRow = CType(oCheckBox.BindingContainer, GridViewRow)
23 
24         '取得目前 GridViewRow 的索引
25         iRowIndex = oGridViewRow.RowIndex
26     End Sub
27 
28 End Class

執行程式後,你會發覺與上一篇文章有相同的效果。這種讓 GridView 欄位可引發 PostBack 的作法是適用其他如 BoundField、HyperLinkField ...等欄位。 不過注意一點,設定欄位內含控件項的動作一定要在 RowCreated 事件中處理;不能在 RowDataBound 事件中處理,因為 RowDataBound 事件只有在 GridView 執行 DataBind 的動作時才會觸發,而 RowCreated 事件是每次頁面 PostBack 時重新產生 GridView 時都會觸發。

posted @ 2007-12-14 19:39 jeff377 阅读(860) 评论(0) 编辑
假設在 GirdView 欄位的 ItemTemplate 中放置 CheckBox 控制項,然後設定該 CheckBox 的 AutoPostBack 為 True,希望在 CheckBox 的CheckedChanged 事件撰寫相關程式碼。

*.aspx 的程式碼如下

<EditItemTemplate>
    <asp:CheckBox ID="CheckBox1" runat="server" AutoPostBack="True" Checked='<%# Bind("Discontinued") %>
     OnCheckedChanged="CheckBox1_CheckedChanged" />
</EditItemTemplate>
一般在 CheckBox 的 CheckedChanged 事件需要它是由那個資料列的 CheckBox 所引發的 PostBack。可以撰寫如下的程式碼,取得控制項所屬的 GridViewRow 及 RowIndex。

 1     Protected Sub CheckBox1_CheckedChanged(ByVal sender As ObjectByVal e As System.EventArgs)
 2         Dim oCheckBox As CheckBox
 3         Dim oGridViewRow As GridViewRow
 4         Dim iRowIndex As Integer
 5 
 6         oCheckBox = CType(sender, CheckBox)
 7 
 8         '取得控制項所屬性 GridViewRow
 9         oGridViewRow = CType(oCheckBox.BindingContainer, GridViewRow)
10 
11         '取得目前 GridViewRow 的索引
12         iRowIndex = oGridViewRow.RowIndex
13     End Sub

posted @ 2007-12-14 19:29 jeff377 阅读(671) 评论(7) 编辑
GridView 中 CommandField 的刪除鈕預設是沒有刪除提示訊息,一般的作法是在 GridView 的 RowDataBound 事件中找到 CommandField 中的按鈕來設定它的刪除訊息。這種方式雖然可以達到需求,不過每次使用時都要自己增加程式碼是個麻煩的動作。

為了開發上的方便,本文中示範如何擴展 CommandField 類別,透過屬性就可以輕易設定刪除提示訊息。首先繼承 CommandField 下來命名為 TBCommandField,新增一個 DeleteConfirmMessage 屬性,用來設定刪除提示訊息;覆寫 InitializeCell 方法,找到按鈕並設定刪除提示訊息。



TBCommandField 類別完整的程式碼如下
 1 Imports System
 2 Imports System.Collections.Generic
 3 Imports System.ComponentModel
 4 Imports System.Text
 5 Imports System.Web
 6 Imports System.Web.UI
 7 Imports System.Web.UI.WebControls
 8 
 9 
10 Public Class TBCommandField
11     Inherits CommandField
12 
13     Private FDeleteConfirmMessage As String = String.Empty
14 
15     ''' <summary>
16     ''' 刪除詢問訊息。
17     ''' </summary>
18     Public Property DeleteConfirmMessage() As String
19         Get
20             Return FDeleteConfirmMessage
21         End Get
22         Set(ByVal value As String)
23             FDeleteConfirmMessage = value
24         End Set
25     End Property
26 
27     ''' <summary>
28     ''' 初始化儲存格。
29     ''' </summary>
30     ''' <param name="cell">儲存格。</param>
31     ''' <param name="cellType"></param>
32     ''' <param name="rowState"></param>
33     ''' <param name="rowIndex"></param>
34     ''' <remarks></remarks>
35     Public Overrides Sub InitializeCell(ByVal cell As DataControlFieldCell, ByVal cellType As DataControlCellType,
              ByVal
 rowState As DataControlRowState, ByVal rowIndex As Integer)
36         MyBase.InitializeCell(cell, cellType, rowState, rowIndex)
37         If Me.ShowDeleteButton AndAlso Me.Visible AndAlso Me.DeleteConfirmMessage <> String.Empty Then
38             SetButtonDeleteConfirm(cell)
39         End If
40     End Sub
41 
42     ''' <summary>
43     ''' 設定刪除鈕的刪除訊息。
44     ''' </summary>
45     ''' <param name="Cell">儲存格。</param>
46     Private Sub SetButtonDeleteConfirm(ByVal Cell As DataControlFieldCell)
47         Dim oControl As Control
48         Dim sScript As String
49 
50         sScript = "if (confirm('" & Me.DeleteConfirmMessage & "')==false) {return false;}"
51 
52         For Each oControl In Cell.Controls
53             If TypeOf (oControl) Is IButtonControl Then
54                 If DirectCast(oControl, IButtonControl).CommandName = "Delete" Then
55                     DirectCast(oControl, WebControl).Attributes("onclick"= sScript
56                     Exit Sub
57                 End If
58             End If
59         Next
60     End Sub
61 End Class
62 

上述程式碼中,是由 SetButtonDeleteConfirm 方法來設定刪除鈕的提示訊息。CommandField 的 ButtonType 可以為 Button、Link、Image 三者之一,依設定不同分別產生的命令鈕為 Button、LinkButton 或 ImageButton 三者之一,不過它們都具有 IButtonControl 介面,所以直接判斷 IButtonControl.CommandName 是否為 "Delete" 來判斷是否為刪除鈕,若是的話就直接設定其 Attributes("onclick") 加入刪除提示訊息。

使用 TBCommandField 的方式與 CommandField 相同,然後直接 aspx 程式碼中設定其 DeleteConfirmMessage 屬性就可以加入刪除提示訊息。

<bee:TBCommandField ShowDeleteButton="True" ShowEditButton="True" DeleteConfirmMessage="確定刪除嗎?" ButtonType="Button" />



posted @ 2007-12-14 02:38 jeff377 阅读(1675) 评论(8) 编辑