BasePage 撰寫 PageCommand 事件 (使用 CallBack)

BasePage 撰寫 PageCommand 事件 (使用 CallBack)

前言

在「BasePage 撰寫 PageCommand 事件」一文中說明如何在 PostBack 時引發 PageCommand 事件,本文將依此繼續擴展,讓 CallBack 也同樣可以引發相同的 PageCommand 事件。

一般的 PostBack 會將整個頁面的資料至伺服端,當伺服端處理完畢時,也是整個頁面 Render 回傳給用戶端呈現;CallBack 是傳開發人員定義的資料至伺服端,當伺服端處理完畢時,只傳回字串給自訂的 JavaScript 函式處理。CallBack 比起 PostBack 相對輕量而有效率,二者可以視時機配合使用。例如頁面資料資料儲存時,整個頁面的資料需要傳至伺服端做儲存動作,這時就適合使用 PostBack 處理;而當執行動作無須傳回頁面的所有資料時,例如在訂單表身登打產品名稱後,需要帶回相對的產品編號、售價、單位...等相關資料,就非常適合使用 CallBack 來處理。

以「BasePage 撰寫 PageCommand 事件」一文中的案例,當用戶端回應訊問後傳入伺服端時執行送審動作時,其實無須傳回頁面所有欄位,只需傳回用戶端的回應值,所以這個案例其實比較適合使用 CallBack 來處理即可,整個程式執行流程如下。

按儲存鈕(用戶端) -> PostBack -> 請假單儲存(伺服端) -> 彈出詢問訊息(用戶端) -> CallBack -> 取得用戶端回應決定是否送審(伺服端)

在本文將描述如何讓 CallBack 也可以引發 PageCommand 事件,而以上述的相同案例,改用 CallBack 方式的 PageCommand 事件來處理。

 

程式實作

以「BasePage 撰寫 PageCommand 事件」中的 TBBasePage 類別及 TBScriptManager 類別做擴展。首先 TBBasePage 類別需實作 CallBack 引發 PageCommand 事件,作法如下。

1.修改 PageCommand 事件引數,加入 CallbackResult 屬性,做為使用 CallBack 執行結果的回傳字串。
2.實作 ICallbackEventHandler 介面。
3.在 RaiseCallbackEvent 方法,判斷 CallBack 的傳入參數,決定是否引發 PageCommand 事件。


''' 頁面基礎類別。
''' </summary>
Public Class TBBasePage
    Inherits System.Web.UI.Page
    Implements System.Web.UI.ICallbackEventHandler

    Private FCallbackResult As String = String.Empty

#Region " PageCommand 事件 "

    ''' <summary>
    ''' DayCommand 事件引數。
    ''' </summary>
    Public Class PageCommandEventArgs
        Inherits System.EventArgs
        Private FCommandName As String = String.Empty
        Private FCommandArgument As String = String.Empty
        Private FCallbackResult As String = String.Empty

        ''' <summary>
        ''' 命令名稱。
        ''' </summary>
        Public Property CommandName() As String
            Get
                Return FCommandName
            End Get
            Set(ByVal value As String)
                FCommandName = value
            End Set
        End Property

        ''' <summary>
        ''' 命令引數。
        ''' </summary>
        Public Property CommandArgument() As String
            Get
                Return FCommandArgument
            End Get
            Set(ByVal value As String)
                FCommandArgument = value
            End Set
        End Property

        ''' <summary>
        ''' CallBack 執行結果的回傳字串。
        ''' </summary>
        Public Property CallbackResult() As String
            Get
                Return FCallbackResult
            End Get
            Set(ByVal value As String)
                FCallbackResult = value
            End Set
        End Property
    End Class

    ''' <summary>
    ''' 頁面命令事件。
    ''' </summary>
    < _
    System.ComponentModel.Description("頁面命令事件。") _
    > _
    Public Event PageCommand(ByVal sender As Object, ByVal e As PageCommandEventArgs)

    ''' <summary>
    ''' 引發 PageCommand 事件。
    ''' </summary>
    Protected Overridable Sub OnPageCommand(ByVal e As PageCommandEventArgs)
        RaiseEvent PageCommand(Me, e)
    End Sub

#End Region

#Region " ICallbackEventHandler 介面 "

    Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
        Dim oArgument() As String
        Dim oEventArgs As PageCommandEventArgs

        oArgument = Split(eventArgument, "$")
        If oArgument.Length = 3 Then
            If SameText(oArgument(0), "PageCommand") Then
                '引發 PageCommand 事件
                oEventArgs = New PageCommandEventArgs()
                oEventArgs.CommandName = oArgument(1)
                oEventArgs.CommandArgument = oArgument(2)
                Me.OnPageCommand(oEventArgs)
                FCallbackResult = oEventArgs.CallbackResult
            End If
        End If
    End Sub

    Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
        Return FCallbackResult
    End Function

#End Region

    ''' <summary>
    ''' 判斷二字串是否相同(不區分大小寫)。
    ''' </summary>
    ''' <param name="S1">第一個字串。</param>
    ''' <param name="S2">第二個字串。</param>
    Public Shared Function SameText(ByVal S1 As String, ByVal S2 As String) As Boolean
        If S1 Is Nothing Then
            Return S2 Is Nothing
        End If
        Return S1.Equals(S2, StringComparison.CurrentCultureIgnoreCase)
    End Function


End Class

然後在 TBScriptManager 類別新增一個 GetCallBackPageCommandEventReference方法,取得使用 CallBack 方式引發 PageCommand 事件的用戶端指令碼。


''' 用戶端指令碼管理。
''' </summary>
Public Class TBScriptManager

    ''' <summary>
    ''' 取得以 CallBack 方式引發 PageCommand 事件的用戶端指令碼。
    ''' </summary>
    ''' <param name="CommandName">命令名稱。</param>
    ''' <param name="CommandArgument">命令引數。</param>
    ''' <param name="ClientCallback">可接收成功的伺服器端事件結果的用戶端事件處理常式名稱。</param>
    ''' <param name="Context">叫用用戶端回呼之用戶端函式的名稱。 </param>
    Public Function GetCallBackPageCommandEventReference(ByVal CommandName As String, _
        ByVal CommandArgument As String, _
        ByVal ClientCallback As String, ByVal Context As String) As String
        Dim sArgument As String

        sArgument = String.Format("'{0}${1}${2}'", PageEvent.PageCommand, CommandName, CommandArgument)
        Return Me.GetCallbackEventReference(FPage, sArgument, ClientCallback, Context)
    End Function

End Class

我們使用 CallBack 方式的 PageCommand 事件來重新改寫程式,第一個階段處理「請假單儲存(伺服端) -> 彈出詢問訊息(用戶端) 」,在下面的程式碼中,訊問訊息的的「確定鈕」是使用 CallBack 方式引發 PageCommand 事件,「取消鈕」則是使用 PostBack 方式引發 PageCommand 事件。


        Dim sTrueScript As String
        Dim sFalseScript As String

        '執行請假單儲存的程式碼

        '儲存完成彈出詢問訊息
        '確定鈕使用 CallBack 引發 PageCommand 事件
        sTrueScript = Me.BeeScript.GetCallBackPageCommandEventReference("SaveConfirm", "True", "null", "")
        '確定鈕使用 PostBack 引發 PageCommand 事件
        sFalseScript = Me.BeeScript.GetPageCommandEventReference("SaveConfirm", "False")
        Me.BeeScript.Confirm("假單要送審嗎?", sTrueScript, sFalseScript)
    End Sub

第二階段在 PageCommand 事件處理用戶端詢問訊息的回應「取得用戶端回應決定是否送審(伺服端)」,在 PageCommand 事件中,無論是使用 PostBack 或 CallBack 都一樣判斷 e.CommandName 及 e.CommandArgument 來決定接續的執行動作即可。在 PageCommand 事件中可以用 Me.IsCallback=True 判斷是否使用 CallBack 方式,若使用 CallBack 方式引發的 PageCommand 事件中需要回傳資料至用戶端,那可以使用 e.CallbackResult 來回傳給自訂的 JavaScript 函式做後續處理。


        If String.Equals(e.CommandName, "SaveConfirm", StringComparison.CurrentCultureIgnoreCase) Then
            If String.Equals(e.CommandArgument, "True", StringComparison.CurrentCultureIgnoreCase) Then
                '按了確定要執行的程式碼
            Else
                '按了取消要執行的程式碼
            End If
        End If
    End Sub

ASP.NET 魔法學院