摘要

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 魔法學院


DotBlogs Tags: BasePage GridView RenderControl

Feedback

  • Jack 2008/8/8 上午 01:03 回覆

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

    請問TBActionPage有錯如何解決,謝謝

  • jeff377 2008/8/8 上午 03:07 回覆

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

    to Jack :

    那行有寫錯,要改為

    DirectCast(Control.Page, TBBasePage).IsVerifyRender = False 

  • saintchou 2009/2/10 上午 01:14 回覆

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

    您好:
    我這樣寫,執行時卻出現
    『型別 'GridView' 的控制項 'GridView2' 必須置於有 runat=server 的表單標記之中。』的錯誤,請問是實麼原因,謝謝您!


    Partial Public Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    End Sub

    Private Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
    If (e.Row.RowState And DataControlRowState.Selected) = DataControlRowState.Selected Then
    Dim oRow As New GridViewRow(0, -1, DataControlRowType.DataRow, e.Row.RowType)
    GridView2.Visible = True
    GridView2.DataBind()
    Dim sHTML As String = WebApplication1.TBBasePage.ControlToHTML(GridView2)
    GridView2.Visible = False
    Dim oCell As New TableCell
    oCell.Text = sHTML
    oCell.ColumnSpan = e.Row.Cells.Count
    oRow.Cells.Add(oCell)
    e.Row.Parent.Controls.AddAt(e.Row.RowIndex + 2, oRow)
    End If
    End Sub

    End Class


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

    ''' <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, TBBasePage).IsVerifyRender = False
    End If
    End If

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

    End Class


    另外,我在 Default.aspx 中也加入了

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

標題 *
名稱 *
Email (將不會被顯示)
Url
回應
登入後使用進階評論
Please add 5 and 3 and type the answer here: