GridView必须放置在runat=";的表单标记内;服务器";即使在GridView位于表单标记内

本文关键字:GridView 表单 quot 于表单 runat 服务器 | 更新日期: 2023-09-27 17:59:10

<form runat="server" id="f1">
    <div runat="server" id="d">
        grid view:
        <asp:GridView runat="server" ID="g">
        </asp:GridView>
    </div>
    <asp:TextBox runat="server" ID="t" TextMode="MultiLine" Rows="20" Columns="50"></asp:TextBox>
</form>

代码背后:

public partial class ScriptTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        g.DataSource = new string[] { "a", "b", "c" };
        g.DataBind();
        TextWriter tw = new StringWriter();
        HtmlTextWriter h = new HtmlTextWriter(tw);    
        d.RenderControl(h);
        t.Text = tw.ToString();
    }
}

即使GridView在runat="server"的from标记中,我仍然会收到这个错误。

有线索吗?

GridView必须放置在runat=";的表单标记内;服务器";即使在GridView位于表单标记内

您正在调用GridView.RenderControl(htmlTextWriter),因此该页面引发一个异常,即服务器控件在Form之外呈现。

您可以通过重写VerifyRenderingInServerForm 来避免此执行

public override void VerifyRenderingInServerForm(Control control)
{
  /* Confirms that an HtmlForm control is rendered for the specified ASP.NET
     server control at run time. */
}

看看这里和这里。

替代覆盖VerifyRenderingInServerForm的方法是在进行渲染时从控件集合中删除网格,然后在页面加载之前完成时将其添加回来。如果你想用一些通用的辅助方法来获取网格html,这是很有帮助的,因为你不必记住添加覆盖。

Control parent = grid.Parent;
int GridIndex = 0;
if (parent != null)
{
    GridIndex = parent.Controls.IndexOf(grid);
    parent.Controls.Remove(grid);
}
grid.RenderControl(hw);
if (parent != null)
{
    parent.Controls.AddAt(GridIndex, grid);
}

避免超控的另一种选择是这样做:

grid.RenderBeginTag(hw);
grid.HeaderRow.RenderControl(hw);
foreach (GridViewRow row in grid.Rows)
{
    row.RenderControl(hw);
}
grid.FooterRow.RenderControl(hw);
grid.RenderEndTag(hw);

在Page_Load之后添加以下内容:

public override void VerifyRenderingInServerForm(Control control)
{
    //base.VerifyRenderingInServerForm(control);
}

请注意,我在函数中不做任何事情。

编辑:蒂姆也回答了同样的问题。:(你也可以在这里找到答案

只想添加另一种方法。我在各种相关线程上看到很多人问你是否可以在不将VerifyRenderingInServerForm添加到父页面的情况下使用它。

你确实可以这样做,但这有点麻烦。

首先创建一个新的Page类,看起来如下所示:

public partial class NoRenderPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    { }
    public override void VerifyRenderingInServerForm(Control control)
    {
        //Allows for printing
    }
    public override bool EnableEventValidation
    {
        get { return false; }
        set { /*Do nothing*/ }
    }
}

不需要与之关联.ASPX。

然后,在要渲染的控件中,可以执行以下操作。

    StringWriter tw = new StringWriter();
    HtmlTextWriter hw = new HtmlTextWriter(tw);
    var page = new NoRenderPage();
    page.DesignerInitialize();
    var form = new HtmlForm();
    page.Controls.Add(form);
    form.Controls.Add(pnl);
    controlToRender.RenderControl(hw);

现在您已经将原始控件呈现为HTML。如果需要,请将控件添加回其原始位置。您现在已经呈现了HTML,页面正常,页面本身没有任何更改。

这是我的代码

protected void btnExcel_Click(object sender, ImageClickEventArgs e)
    {
        if (gvDetail.Rows.Count > 0)
        {
            System.IO.StringWriter stringWrite1 = new System.IO.StringWriter();
            System.Web.UI.HtmlTextWriter htmlWrite1 = new HtmlTextWriter(stringWrite1);
            gvDetail.RenderControl(htmlWrite1);
            gvDetail.AllowPaging = false;
            Search();
            sh.ExportToExcel(gvDetail, "Report");
        }
    }
    public override void VerifyRenderingInServerForm(Control control)
    {
        /* Confirms that an HtmlForm control is rendered for the specified ASP.NET
           server control at run time. */
    }

Tim Schmelter的回答对我帮助很大,但我还需要做一件事才能让它在我的aspx页面上运行。我正在使用此代码通过电子邮件发送嵌入的GridView控件(作为HTML(,以实现报表自动化。

除了添加覆盖子,我还必须在Me.HHandles.onunload中执行render((,否则我在RenderControl行上会出错。

Protected Sub Page_After_load(sender As Object, e As EventArgs) Handles Me.Unload
If runningScheduledReport Then
    Dim stringBuilder As StringBuilder = New StringBuilder()
    Dim stringWriter As System.IO.StringWriter = New System.IO.StringWriter(stringBuilder)
    Dim htmlWriter As HtmlTextWriter = New HtmlTextWriter(stringWriter)
    GridView1.RenderControl(htmlWriter)
    Dim htmlcode As String = stringBuilder.ToString()
    
    Func.SendEmail(Context.Request.QueryString("email").ToString, htmlcode, "Auto Report - Agent Efficiency", Nothing)
End If
End Sub