即使GridView位于表单标签内,也必须将GridView置于带有runat =“ server”的表单标签内


86
<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标记内,仍然出现此错误。

有什么线索吗?


2
如果有人使用的母版页已经具有一个表单标签(可能已经或可能尚未runat="server"在其<form>标签中声明),我以前就已经看到过。只是想一想...
2011年

@Lloyd:但是我没有任何母版页,我创建此页仅用于测试此错误。
teenup 2011年

嗨,我复制了您的代码,但无法复制问题。您能否将整个文件的内容(每一行)放入您的问题中,或将其粘贴?谢谢
christofr

Answers:


174

您正在调用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. */
}

看到这里这里


我有一个GridView,我想将其内容呈现为电子邮件消息,这就是为什么我需要将其呈现为不正确的形式。我无法覆盖此方法,因为宿主页属于Sharepoint。我的网格是共享点页面中Web部件内的用户控件。
teenup 2011年

此外,当我将GridView直接动态地直接添加到HtmlForm,然后对其进行呈现时,它会完美呈现。这意味着它仅需要在网格外部存在表单。但是,当我将该DIV动态添加到HtmlForm中时,尽管Grid是DIV的子级,并且也随同它一起添加到了HtmlForm中,但还是再次出现此错误。
teenup 2011年

如果您的网格位于.ascx用户控件内,则此方法将不起作用。在这种情况下,请参见克里斯·穆林斯的回答。我既使用了Tim和Chris的技术,又表现出色。
泰勒·布朗

我喜欢一个优雅的解决方案!让我激动:D
Nikolay

3
很棒。请注意,您可能会收到一条错误消息:“只能在Render()期间调用RegisterForEventValidation;” 如果已设置,请确保在页面标记中将EventValidation设置为false。
Al Belmondo 2014年

29

重写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);

机灵!我明天试试。
teenup 2011年

当尝试在asp用户控件(.ascx)中渲染网格时,使用第一种方法对我来说非常有用。
泰勒·布朗

3
1,如果gridview包含LinkBut​​ton之类的控件是行不通的-它给出了``LinkBut​​ton类型的控件必须放置在带有runat = server的表单标记中''的错误。2.您能否解释一下这种技术为什么起作用?
BornToCode 2015年

@BornToCode在代码中禁用对gridview的排序。
阿迪太阳能

14

在您的Page_Load之后添加以下内容:

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

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

编辑:蒂姆回答了同样的事情。:)您也可以在这里找到答案


2

只是想添加另一种方法。我已经在多个相关线程上看到多个人询问您是否可以在不将其添加到父页面的情况下使用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,页面正常,并且页面本身没有更改。


@DanielEdwards DesignerInitialize()为您做什么?
JJS

这行得通,但是我需要用来HttpContext.Current.Server.Execute(page, writer, false);编写HTML-调用controlToRender.RenderControl(hw);没有引发任何控件事件,例如,Page_Load因此在控件呈现时,它为空。
DGibbs

0

这是我的代码

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. */
    }

为什么您在回答了5年后又添加了这个答案?这是相同的答案。
Mukus '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.