使用 BasePage 來解決 GridView 執行 RenderControl 產生的錯誤

使用 BasePage 來解決 GridView 執行 RenderControl 產生的錯誤

摘要

GridView 控制項常有需要匯出 Excel 的需求,一般都是將 GridView 使用 RenderControl 來輸出其 HTML 程式碼。本文即在討論 RenderControl 所產生的問題及解決方式,不過本文是透過 BasePage 的方式,讓 RenderControl 的相關處理動作更簡化。

手動解決 RenderControl 所產生的問題

下面的 ControlToHTML 函式,主要是將控制項轉換為對應的 HTML 程式碼。

    ''' <summary>
    ''' 將控制項轉換為對應的 HTML 程式碼。
    ''' </summary>
    ''' <param name="Control">控制項。</param>
    Public Shared Function ControlToHTML(ByVal Control As System.Web.UI.Control) As String
        Dim sHTML As String = String.Empty
        Dim oTextWriter As New System.IO.StringWriter()
        Dim oHTMLWriter As New System.Web.UI.HtmlTextWriter(oTextWriter)

        Control.RenderControl(oHTMLWriter)
        sHTML = oTextWriter.ToString()
        Return sHTML
    End Function

你可以整個 GridView 控制項傳入 ControlToHTML 來取得它的 HTML 程式碼,不過當執行此方法時,會遇到由 Page.VerifyRenderingInServerForm 方法釋出的錯誤訊息。

當執行下面的程式碼時

Dim sHTML As String = ControlToHTML(GridView1)

會產生錯誤訊息

型別 'GridView' 的控制項 'GridView1' 必須置於有 runat=server 的表單標記之中。

要解決這個問題就是讓 Page 不要執行 VerifyRenderingInServerForm 方法,所以 Page 要覆寫 VerifyRenderingInServerForm 方法,而不做任何事。

Public Overrides Sub VerifyRenderingInServerForm(ByVal Control As System.Web.UI.Control)
     '覆寫,不執行 MyBase.VerifyRenderingInServerForm 方法,解決執行 RenderControl 產生的錯誤
End Sub

接下來繼續執行程式,若 GridView 有 CommandFIeld 或分頁時,它會去做事件驗證的動作,而會引發另一個錯誤訊息

RegisterForEventValidation 只能在 Render(); 期間呼叫

要解決這個問題,可以切換到 aspx 程式碼中,在 <%@ Page %> 中加入 EnableEventValidation="false" 即可。

<%@ Page Language="VB" AutoEventWireup="false" EnableEventValidation="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

 

 

使用 BasePage 解決 RenderControl 所產生的問題

雖然上述的方式可以解決 RenderControl 產生的問題,可是似乎有點太麻煩,有沒有更簡單的方式呢?我們用 BasePage 來處理這個問題,不用當有這類需求時還要去手動故這些設定。

TBBasePage 繼承 Page,新增一個 IsVerifyRender 屬性(預設為 True),來決定是否執行 MyBase.VerifyRenderingInServerForm 方法。首先覆寫 VerifyRenderingInServerForm 方法,當 IsVerifyRender="False" 時,不會去執行 MyBase.VerifyRenderingInServerForm 方法;另外覆寫 EnableEventValidation 方法,當 IsVerifyRender="False" 則傳回 False。當我們要用 RenderControl 來輸出控制項的 HTML 碼時,只需先設定 IsVerifyRender = "False" 即可。

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

    Private FIsVerifyRender As Boolean = True

    ''' <summary>
    ''' 是否執行 VerifyRenderingInServerForm 方法。
    ''' </summary>
    Public Property IsVerifyRender() As Boolean
        Get
            Return FIsVerifyRender
        End Get
        Set(ByVal value As Boolean)
            FIsVerifyRender = value
        End Set
    End Property

    ''' <summary>
    ''' 覆寫。
    ''' </summary>
    ''' <param name="Control"></param>
    ''' <remarks></remarks>
    Public Overrides Sub VerifyRenderingInServerForm(ByVal Control As System.Web.UI.Control)
        If Me.IsVerifyRender Then
            MyBase.VerifyRenderingInServerForm(Control)
        End If
    End Sub

    ''' <summary>
    ''' 覆寫。啟用事件驗證動作。
    ''' </summary>
    Public Overrides Property EnableEventValidation() As Boolean
        Get
            If Me.IsVerifyRender Then
                Return MyBase.EnableEventValidation
            Else
                Return False
            End If
        End Get
        Set(ByVal value As Boolean)
            MyBase.EnableEventValidation = value
        End Set
    End Property

End Class

有了 TBBasePage 的 IsVerifyRender 屬性後,我們就可以將上述的 ControlToHTML 函式,改寫如下。當 GridView 控制項置放在 TBBasePage 時,執行 ControlToHTML 函式時,不需另行設定即能正常執行。

    ''' <summary>
    ''' 將控制項轉換為對應的 HTML 程式碼。
    ''' </summary>
    ''' <param name="Control">控制項。</param>
    Public Shared Function ControlToHTML(ByVal Control As System.Web.UI.Control) As String
        Dim sHTML As String = String.Empty
        Dim oTextWriter As New System.IO.StringWriter()
        Dim oHTMLWriter As New System.Web.UI.HtmlTextWriter(oTextWriter)

        If Control.Page IsNot Nothing Then
            If TypeOf Control.Page Is TBBasePage Then
                DirectCast(Control.Page, TBActionPage).IsVerifyRender = False
            End If
        End If

        Control.RenderControl(oHTMLWriter)
        sHTML = oTextWriter.ToString()
        Return sHTML
    End Function

ASP.NET 魔法學院