GridView doit être placé dans une balise de formulaire avec runat = "server" même après que GridView se trouve dans une balise de formulaire


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>

Code derrière:

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();
    }
}

Même le GridView est dans une balise from avec runat = "server", j'obtiens toujours cette erreur.

Des indices s'il vous plait?


2
J'ai déjà vu cela si quelqu'un utilise une page maître qui a déjà une balise de formulaire (qui peut ou non être déjà déclarée runat="server"dans sa <form>balise). Juste une pensée ...
lhan

@Lloyd: Mais je n'ai pas de page maître, j'ai créé cette page uniquement pour tester cette erreur.
teenup le

Bonjour, j'ai copié votre code mais je ne parviens pas à reproduire le problème. Pouvez-vous s'il vous plaît mettre tout le contenu du fichier (chaque ligne) dans votre question, ou le coller? Merci
christofr

Réponses:


174

Vous appelez GridView.RenderControl(htmlTextWriter), donc la page lève une exception selon laquelle un contrôle serveur a été rendu en dehors d'un formulaire.

Vous pouvez éviter cette exécution en remplaçant VerifyRenderingInServerForm

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

Voir ici et ici .


J'ai un GridView dont je veux rendre le contenu dans un message électronique, c'est pourquoi je dois le rendre hors forme. Je ne peux pas remplacer cette méthode car la page hôte est de Sharepoint. My Grid est un Usercontrol dans un composant WebPart dans une page sharepoint.
teenup le

De plus, lorsque j'ajoute ce GridView directement à un HtmlForm dynamiquement, puis que je le rende, il rend parfaitement. Cela signifie qu'il ne nécessite que la présence d'un formulaire hors grille. Mais, lorsque j'ajoute dynamiquement ce DIV au HtmlForm, cette erreur survient à nouveau, bien que le Grid soit un enfant de DIV et également ajouté à HtmlForm avec lui.
teenup le

cela ne fonctionnera pas si votre grille se trouve dans un contrôle utilisateur .ascx. dans ce cas, voir la réponse de Chris Mullins ci-dessous. J'ai utilisé les techniques de Tim et Chris et elles fonctionnent très bien.
Taylor Brown

J'adore une solution élégante! M'excite: D
Nikolay

3
A très bien fonctionné. Juste un avertissement, vous pouvez obtenir une erreur disant "RegisterForEventValidation ne peut être appelé que pendant Render ();" Si tel est le cas, assurez-vous de définir EventValidation sur false dans le balisage de la page.
Al Belmondo

29

Une alternative à la substitution de VerifyRenderingInServerForm consiste à supprimer la grille de la collection de contrôles pendant que vous effectuez le rendu, puis à la rajouter lorsque vous avez terminé avant le chargement de la page. Ceci est utile si vous souhaitez avoir une méthode d'assistance générique pour obtenir le code HTML de la grille, car vous n'avez pas à vous rappeler d'ajouter le remplacement.

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);
}

Une autre alternative pour éviter le remplacement est de faire ceci:

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

Adroit!! Je vais l'essayer demain.
teenup le

en essayant de rendre la grille dans un contrôle utilisateur asp (.ascx), l'utilisation de la 1ère méthode a très bien fonctionné pour moi.
Taylor Brown

3
1. Cela ne fonctionne pas si gridview contient des contrôles comme LinkButton - il donne 'Le contrôle de type' LinkButton 'doit être placé dans une balise de formulaire avec l'erreur runat = server'. 2.Pouvez-vous expliquer pourquoi cette technique fonctionne-t-elle?
BornToCode

@BornToCode Désactivez le tri pour votre grille dans le code.
Adi Solar

14

Juste après votre Page Load, ajoutez ceci:

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

Notez que je ne fais rien dans la fonction.

EDIT: Tim a répondu à la même chose. :) Vous pouvez également trouver la réponse ici


2

Je veux juste ajouter une autre façon de faire cela. J'ai vu plusieurs personnes sur divers threads connexes vous demander si vous pouvez utiliser VerifyRenderingInServerForm sans l'ajouter à la page parent.

En fait, vous pouvez le faire, mais c'est un peu bizarre.

Commencez par créer une nouvelle classe Page qui ressemble à ceci:

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

N'a pas besoin d'avoir un .ASPX associé.

Ensuite, dans le contrôle que vous souhaitez rendre, vous pouvez faire quelque chose comme ce qui suit.

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

Votre contrôle d'origine est maintenant rendu au format HTML. Si vous en avez besoin, remettez le contrôle dans sa position d'origine. Vous avez maintenant le HTML rendu, la page comme d'habitude et aucune modification de la page elle-même.


@DanielEdwards que fait DesignerInitialize () pour vous?
JJS

Cela fonctionne mais j'avais besoin d'utiliser HttpContext.Current.Server.Execute(page, writer, false);pour écrire le HTML - l'appel controlToRender.RenderControl(hw);n'a déclenché aucun des événements de contrôle, par exemple Page_Load, pendant le rendu du contrôle, il était vide.
DGibbs

0

Voici mon code

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

Pourquoi avez-vous ajouté cette réponse 5 ans après sa réponse? Et c'est la même réponse.
Mukus
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.