BasePage 撰寫 PageCommand 事件

BasePage 撰寫 PageCommand 事件

前言

在「撰寫自用 Confirm 方法」一文中提到的「案例三:先執行伺服端程式再彈出詢問訊息,依用戶端回應再接續執行」,當用戶端回應詢問訊息後,會呼叫 __doPostBack() 函式來產生 PostBack 的動作,頁面再自行判斷 Me.Request.Form("__EVENTTARGET") 及 Me.Request.Form("__EVENTARGUMENT")  來處理後序的作業。可是這樣處理 PostBack 的方式略顯麻煩,換個角度思考,若 Page 也能像 GridView 一樣具有類似 RowCommand 的事件,可以處理這類的 PostBack 那不是更方便了嗎?所以本文將在 BasePage 加入 PageCommand 事件,針對這個案例改用 PageCommand 來處理。

 

程式實作

我們將使用「撰寫自用的 ScriptManager 來管理用戶端指令碼」文中提及的 TBBasePage 類別及 TBScriptManager 類別為基礎做擴展。首先在 TBBasePage 新增一個 PageCommand 事件,作法如下。

1.定義 PageCommand 事件。
2.新增 EventTarget 唯讀屬性,傳回 Me.Request.Form("__EVENTTARGET")。
3.新增 EventArgument 唯讀屬性,傳回 Me.Request.Form("__EVENTARGUMENT")。
4.覆寫 OnLoad 方法,判斷 EventTarget 及 EventArgument 屬性值,來決定是否引發 PageCommand 事件。

 


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

#Region " PageCommand 事件 "

    ''' <summary>
    ''' DayCommand 事件引數。
    ''' </summary>
    Public Class PageCommandEventArgs
        Inherits System.EventArgs
        Private FCommandName As String = String.Empty
        Private FCommandArgument 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

    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

    ''' <summary>
    ''' 觸發 PostBack 的控制項 UniqueID。
    ''' </summary>
    Public ReadOnly Property EventTarget() As String
        Get
            Return Me.Request.Form("__EVENTTARGET")
        End Get
    End Property

    ''' <summary>
    ''' 觸發 PostBack 動作事件引數 。
    ''' </summary>
    Public ReadOnly Property EventArgument() As String
        Get
            Return Me.Request.Form("__EVENTARGUMENT")
        End Get
    End Property

    ''' <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

    ''' <summary>
    ''' 覆寫。引發 Load 事件。
    ''' </summary>
    Protected Overrides Sub OnLoad(ByVal e As EventArgs)
        Dim oArgument() As String
        Dim oEventArgs As PageCommandEventArgs

        MyBase.OnLoad(e)

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

End Class

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

 


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

    ''' <summary>
    ''' 取得引發 PageCommand 事件的用戶端指令碼。
    ''' </summary>
    ''' <param name="CommandName">命令名稱。</param>
    ''' <param name="CommandArgument">命令引數。</param>
    Public Function GetPageCommandEventReference(ByVal CommandName As String, ByVal CommandArgument As String) As String
        Dim sArgument As String

        sArgument = String.Format("{0}${1}${2}", "PageCommand", CommandName, CommandArgument)
        Return Me.GetPostBackEventReference(FPage, sArgument)
    End Function

End Class

PageCommand 事件完成了,我們把「案例三:先執行伺服端程式再彈出詢問訊息,依用戶端回應再接續執行」使用 PageCommand 來改寫,它的程式流程如下。

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

第一個階段處理「請假單儲存(伺服端) -> 彈出詢問訊息(用戶端) 」,在下面的程式碼中,訊問訊息的回應結果無論是「確定」或「取消」都會引發 PageCommand 事件,CommandName 都是 "SaveConfirm",差別是 CommandArgument 的值不同。

 


    Protected Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
        Dim sTrueScript As String
        Dim sFalseScript As String

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

        '儲存完成彈出詢問訊息
        sTrueScript = Me.BeeScript.GetPageCommandEventReference("SaveConfirm", "True")
        sFalseScript = Me.BeeScript.GetPageCommandEventReference("SaveConfirm", "False")
        Me.BeeScript.Confirm("假單要送審嗎?", sTrueScript, sFalseScript)
    End Sub

第二階段在 PageCommand 事件處理用戶端詢問訊息的回應「取得用戶端回應決定是否送審(伺服端)」,在 PageCommand 事件中,我們只需判斷 e.CommandName 及 e.CommandArgument 來決定接續的執行動作即可。


    Protected Sub Page_PageCommand(ByVal sender As Object, ByVal e As Bee.Web.TBBasePage.PageCommandEventArgs) Handles Me.PageCommand
        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 魔法學院