GridView должен быть помещен внутри тега формы с помощью runat = "server" даже после того, как GridView находится в теге формы

<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", но я получаю эту ошибку.

Любые подсказки, пожалуйста?

Ответ 1

Вы вызываете GridView.RenderControl(htmlTextWriter), поэтому на странице возникает исключение, которое Server-Control было отображено вне формы.

Вы можете избежать этого исключения, переопределив VerifyRenderingInServerForm

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

Смотрите здесь и здесь.

Ответ 2

Альтернативой переопределению VerifyRenderingInServerForm является удаление сетки из коллекции элементов управления во время рендеринга, а затем добавление ее обратно, когда вы закончите до загрузки страницы. Это полезно, если вы хотите, чтобы какой-то общий вспомогательный метод получил grid 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);

Ответ 3

Сразу после того, как ваш Page_Load добавьте это:

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

Обратите внимание, что я ничего не делаю в этой функции.

EDIT: Тим ответил на одно и то же.:) Вы также можете найти ответ здесь

Ответ 4

Вот мой код

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

Просто хочу добавить другой способ сделать это. Я видел, как несколько человек из разных связанных друг с другом вопросов спрашивают, можете ли вы использовать VerifyRenderingInServerForm, не добавляя его на родительскую страницу.

На самом деле вы можете это сделать, но это немного ловушка.

Сначала создайте новый класс страницы, который выглядит примерно так:

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-рендеринг, страница как обычно и никаких изменений на самой странице.