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>)。ちょうど思考...
lhan

@Lloyd:しかし、マスターページはありません。このエラーをテストするためだけに、このページを作成しました。
ティーンアップ2011年

こんにちは、コードをコピーしましたが、問題を再現できません。ファイルの内容全体(すべての行)を質問に入れてください、またはそれをペーストビンしてください。ありがとう
christofr 2011年

回答:


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は、SharePointページのWebパーツ内のユーザーコントロールです。
ティーンアップ2011年

また、そのGridViewをHtmlFormに直接動的に追加してからレンダリングすると、完全にレンダリングされます。これは、グリッドの外側にフォームが存在することだけが必要であることを意味します。しかし、そのDIVをHtmlFormに動的に追加すると、グリッドはDIVの子であり、それとともにHtmlFormにも追加されますが、このエラーが再び発生します。
ティーンアップ2011年

グリッドが.ascxユーザーコントロール内にある場合、これは機能しません。その場合は、以下のChrisMullinsの回答を参照してください。私はティムとクリスの両方のテクニックを使用しましたが、それらはうまく機能します。
テイラーブラウン

私はエレガントなソリューションが大好きです!私を興奮させます:D
ニコライ2014年

3
うまくいきました。「RegisterForEventValidationはRender();中にのみ呼び出すことができます」というエラーが表示される場合があります。その場合は、ページのマークアップでEventValidationをfalseに設定してください。
アルベルモンド2014

29

VerificationRenderingInServerFormをオーバーライドする代わりに、レンダリングの実行中にコントロールコレクションからグリッドを削除し、ページが読み込まれる前に終了したらグリッドを追加し直すこともできます。これは、オーバーライドを追加することを覚えておく必要がないため、グリッド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);

器用!!明日やってみます。
ティーンアップ2011年

aspユーザーコントロール(.ascx)内でグリッドをレンダリングしようとしたとき、最初の方法を使用するとうまくいきました。
テイラーブラウン

3
1.gridviewにLinkBut​​tonのようなコントロールが含まれている場合は機能しません-「タイプのコントロール」「LinkBut​​ton」はrunat = serverのエラーでフォームタグ内に配置する必要があります。2.この手法が機能する理由を説明してください。
BornToCode 2015年

@BornToCodeコード内のグリッドビューの並べ替えを無効にします。
アディソーラー

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 2016年

これは機能します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年後になぜこの回答を追加したのですか?そしてそれは同じ答えです。
粘液2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.