摘要
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