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>тезі). Просто думка ...
Лхан,

@Lloyd: Але у мене немає головної сторінки, я створив цю сторінку лише для тестування цієї помилки.
teenup

Привіт, я скопіював ваш код, але не можу повторити проблему. Чи можете ви, будь ласка, додати до свого запитання весь вміст файлу (кожен рядок), або вставити його? Дякую
christofr

Відповіді:


174

Ви телефонуєте GridView.RenderControl(htmlTextWriter), отже, на сторінці з’являється виняток, що елемент керування сервером відображався поза формою.

Ви можете уникнути цього виключення, замінивши 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. My Grid - це UserControl усередині веб-частини на сторінці Sharepoint.
teenup

Крім того, коли я додаю, що GridView динамічно безпосередньо до HtmlForm, а потім відтворює його, він чудово відображається. Це означає, що для цього потрібна лише наявність форми поза сіткою. Але, коли я динамічно додаю цей DIV до HtmlForm, ця помилка знову виникає, хоча Grid є дочірнім елементом DIV і також додається до HtmlForm разом з ним.
teenup

це не буде працювати, якщо ваша сітка знаходиться всередині елемента керування .ascx. у цьому випадку див. відповідь Кріса Маллінза нижче. Я використовував і техніку Тіма, і Кріса, і вони чудово працюють.
Тейлор Браун

Я люблю елегантне рішення! Мене збуджує: D
Микола

3
Працював чудово. Попереджуючи, ви можете отримати повідомлення про помилку: "RegisterForEventValidation можна викликати лише під час Render ();" Якщо так встановлено, обов’язково встановіть для параметра EventValidation значення false у розмітці сторінки.
Аль Бельмондо,

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 у коді.
Аді Солар

14

Відразу після вашої Page_Load додайте це:

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

Зверніть увагу, що я нічого не роблю у функції.

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


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 років після відповіді? І це та сама відповідь.
Мукус,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.