<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 behind:
public partial class ScriptTest : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
g.DataSource = new string[] { "a", "开发者_C百科b", "c" };
g.DataBind();
TextWriter tw = new StringWriter();
HtmlTextWriter h = new HtmlTextWriter(tw);
d.RenderControl(h);
t.Text = tw.ToString();
}
}
Even the GridView is within a from tag with runat="server", still I am getting this error.
Any clues please ?
You are calling GridView.RenderControl(htmlTextWriter)
, hence the page raises an exception that a Server-Control was rendered outside of a Form.
You could avoid this execption by overriding VerifyRenderingInServerForm
public override void VerifyRenderingInServerForm(Control control)
{
/* Confirms that an HtmlForm control is rendered for the specified ASP.NET
server control at run time. */
}
See here and here.
An alternative to overriding VerifyRenderingInServerForm is to remove the grid from the controls collection while you do the render, and then add it back when you are finished before the page loads. This is helpful if you want to have some generic helper method to get grid html because you don't have to remember to add the override.
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);
}
Another alternative to avoid the override is to do this:
grid.RenderBeginTag(hw);
grid.HeaderRow.RenderControl(hw);
foreach (GridViewRow row in grid.Rows)
{
row.RenderControl(hw);
}
grid.FooterRow.RenderControl(hw);
grid.RenderEndTag(hw);
Just after your Page_Load add this:
public override void VerifyRenderingInServerForm(Control control)
{
//base.VerifyRenderingInServerForm(control);
}
Note that I don't do anything in the function.
EDIT: Tim answered the same thing. :) You can also find the answer Here
Just want to add another way of doing this. I've seen multiple people on various related threads ask if you can use VerifyRenderingInServerForm without adding it to the parent page.
You actually can do this but it's a bit of a bodge.
First off create a new Page class which looks something like the following:
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*/ }
}
}
Does not need to have an .ASPX associated with it.
Then in the control you wish to render you can do something like the following.
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);
Now you've got your original control rendered as HTML. If you need to, add the control back into it's original position. You now have the HTML rendered, the page as normal and no changes to the page itself.
Here is My 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. */
}
Tim Schmelter's answer helped me a lot, but I had to do one more thing to get it to work on my aspx page. I am using this code to email an embedded GridView control (as HTML), for report automation.
In addition to adding the override sub, I had to do the render() in Me.Handles.onunload, or else I got an error on the RenderControl line.
Protected Sub Page_After_load(sender As Object, e As EventArgs) Handles Me.Unload
If runningScheduledReport Then
Dim stringBuilder As StringBuilder = New StringBuilder()
Dim stringWriter As System.IO.StringWriter = New System.IO.StringWriter(stringBuilder)
Dim htmlWriter As HtmlTextWriter = New HtmlTextWriter(stringWriter)
GridView1.RenderControl(htmlWriter)
Dim htmlcode As String = stringBuilder.ToString()
Func.SendEmail(Context.Request.QueryString("email").ToString, htmlcode, "Auto Report - Agent Efficiency", Nothing)
End If
End Sub
精彩评论