前言
在「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