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

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 находится внутри тега from с runat = "server", но я все равно получаю эту ошибку.

Какие-нибудь подсказки, пожалуйста?

подросток
источник
2
Я видел это раньше, если кто-то использует главную страницу, у которой уже есть тег формы (который может или не может уже быть объявлен runat="server"в этом <form>теге). Просто мысль ...
lhan
@Lloyd: Но у меня нет мастер-страницы, я создал эту страницу только для проверки этой ошибки.
teenup
Привет, я скопировал ваш код, но не могу воспроизвести проблему. Не могли бы вы поместить в свой вопрос все содержимое файла (каждую строку) или вставить его? Спасибо
Christofr

Ответы:

174

Вы вызываете 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. */
}

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

Тим Шмелтер
источник
У меня есть GridView, содержимое которого я хочу отобразить в сообщении электронной почты, поэтому мне нужно отобразить его вне формы. Я не могу переопределить этот метод, потому что главная страница принадлежит Sharepoint. Моя сетка - это элемент управления пользователя внутри веб-части на странице sharepoint.
teenup
Кроме того, когда я динамически добавляю этот GridView непосредственно в HtmlForm, а затем визуализирую его, он отлично отображается. Это означает, что требуется только наличие формы вне сетки. Но когда я динамически добавляю этот DIV в HtmlForm, эта ошибка снова появляется, хотя Grid является дочерним элементом DIV и также добавляется в HtmlForm вместе с ним.
teenup
это не сработает, если ваша сетка находится внутри пользовательского элемента управления .ascx. в этом случае см. ответ Криса Маллинза ниже. Я использовал методы Тима и Криса, и они отлично работают.
Тейлор Браун,
Обожаю элегантное решение! Меня возбуждает: D
Николай
3
Сработало отлично. Предупреждаем, что вы можете получить сообщение об ошибке: «RegisterForEventValidation можно вызвать только во время Render ();» Если это так, не забудьте установить для EventValidation значение false в разметке страницы.
Al Belmondo
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
при попытке визуализировать сетку внутри пользовательского элемента управления asp (.ascx) использование 1-го метода отлично сработало для меня.
Тейлор Браун
3
1.Это не работает, если gridview содержит элементы управления, такие как LinkButton - он дает «Элемент управления типа« LinkButton »должен быть помещен в тег формы с ошибкой runat = server. 2. Не могли бы вы объяснить, почему работает эта техника?
BornToCode
@BornToCode Отключить сортировку для вашего gridview в коде.
Adi Solar
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. */
    }
vipin
источник
Почему вы добавили этот ответ через 5 лет после того, как на него ответили? И это тот же ответ.
Мукус