UserControl 的 RenderControl 要求在 (C# .NET) 中使用表单标记

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/334382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:37:21  来源:igfitidea点击:

UserControl's RenderControl is asking for a form tag in (C# .NET)

c#html.netuser-controls

提问by Jon Smock

I asked how to render a UserControl's HTMLand got the code working for a dynamically generated UserControl.

我询问了如何呈现 UserControl 的 HTML并让代码为动态生成的 UserControl 工作。

Now I'm trying to use LoadControl to load a previously generated Control and spit out its HTML, but it's giving me this:

现在我正在尝试使用 LoadControl 加载以前生成的控件并吐出它的 HTML,但它给了我这个:

Control of type 'TextBox' must be placed inside a form tag with runat=server.

'TextBox' 类型的控件必须放置在带有 runat=server 的表单标签内。

I'm not actually adding the control to the page, I'm simply trying to grab its HTML. Any ideas?

我实际上并没有将控件添加到页面,我只是想获取它的 HTML。有任何想法吗?

Here's some code I'm playing with:

这是我正在玩的一些代码:

TextWriter myTextWriter = new StringWriter();
HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);

UserControl myControl = (UserControl)LoadControl("newUserControl.ascx");
myControl.RenderControl(myWriter);

return myTextWriter.ToString();

采纳答案by Tom Jelen

Alternatively you could disable the ServerForm/Event-validation on the page that is rendering the control to a string.

或者,您可以在将控件呈现为字符串的页面上禁用 ServerForm/Event-validation。

The following example illustrates how to do this.

以下示例说明了如何执行此操作。

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string rawHtml = RenderUserControlToString();
    }

    private string RenderUserControlToString()
    {
        UserControl myControl = (UserControl)LoadControl("WebUserControl1.ascx");

        using (TextWriter myTextWriter = new StringWriter())
        using (HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter))
        {
            myControl.RenderControl(myWriter);

            return myTextWriter.ToString();
        }
    }

    public override void VerifyRenderingInServerForm(Control control)
    { /* Do nothing */ }

    public override bool EnableEventValidation
    {
        get { return false; }
        set { /* Do nothing */}
    }
}

回答by Bob

You can either add a form to your user control, or use a regular html input box

您可以向用户控件添加表单,也可以使用常规的 html 输入框

 <input type="text" />

Edit: If you are trying to do something AJAXy, maybe you want something like this http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx

编辑:如果你正在尝试做一些 AJAXy,也许你想要这样的 http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx

    public static string RenderView<D>(string path, D dataToBind)
    {
        Page pageHolder = new Page();
        UserControl viewControl = (UserControl) pageHolder.LoadControl(path);
        if(viewControl is IRenderable<D>)
        {
            if (dataToBind != null)
            {
                ((IRenderable<D>) viewControl).PopulateData(dataToBind);
            }
        }
        pageHolder.Controls.Add(viewControl);
        StringWriter output = new StringWriter();
        HttpContext.Current.Server.Execute(pageHolder, output, false);

        return output.ToString();
    }

You can remove the data binding part if not needed.

如果不需要,您可以删除数据绑定部分。

回答by TcKs

You can add the control into page, render html and then remove the control from page.

您可以将控件添加到页面中,呈现 html,然后从页面中删除控件。

Or try this:

或者试试这个:

Page tmpPage = new TempPage(); // temporary page
Control tmpCtl = tmpPage.LoadControl( "~/UDynamicLogin.ascx" );
//the Form is null that's throws an exception
tmpPage.Form.Controls.Add( tmpCtl );

StringBuilder html = new StringBuilder();
using ( System.IO.StringWriter swr = new System.IO.StringWriter( html ) ) {
    using ( HtmlTextWriter writer = new HtmlTextWriter( swr ) ) {
        tmpPage.RenderControl( writer );
    }
}

回答by Jon Smock

This is a dirty solution I used for the moment (get it working then get it right, right?).

这是我目前使用的一个肮脏的解决方案(让它工作然后正确,对吧?)。

I had already created a new class that inherits the UserControl class and from which all other "UserControls" I created were derived. I called it formPartial (nod to Rails), and this is going inside the public string renderMyHTML() method:

我已经创建了一个继承 UserControl 类的新类,我创建的所有其他“UserControls”都是从该类派生的。我称它为 formPartial(向 Rails 致敬),这是在公共字符串 renderMyHTML() 方法中的:

TextWriter myTextWriter = new StringWriter();
HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);

UserControl myDuplicate = new UserControl();
TextBox blankTextBox;

foreach (Control tmpControl in this.Controls)
{
    switch (tmpControl.GetType().ToString())
    {
        case "System.Web.UI.LiteralControl":
            blankLiteral = new LiteralControl();
            blankLiteral.Text = ((LiteralControl)tmpControl).Text;
            myDuplicate.Controls.Add(blankLiteral);
            break;
        case "System.Web.UI.WebControls.TextBox":
            blankTextBox = new TextBox();
            blankTextBox.ID = ((TextBox)tmpControl).ID;
            blankTextBox.Text = ((TextBox)tmpControl).Text;
            myDuplicate.Controls.Add(blankTextBox);
            break;

            // ...other types of controls (ddls, checkboxes, etc.)

    }
}

myDuplicate.RenderControl(myWriter);
return myTextWriter.ToString();

Drawbacks off the top of my head:

我头顶的缺点:

  1. You need a case statement with every possible control (or controls you expect).
  2. You need to transfer all the important attributes from the existing control (textbox, etc) to the new blank control.
  3. Doesn't take full advantage of Controls' RenderControl method.
  1. 您需要一个包含所有可能控件(或您期望的控件)的 case 语句。
  2. 您需要将所有重要属性从现有控件(文本框等)转移到新的空白控件。
  3. 没有充分利用 Controls 的 RenderControl 方法。

It'd be easy to mess up 1 or 2. Hopefully, though, this helps someone else come up with a more elegant solution.

很容易弄乱 1 或 2。不过,希望这有助于其他人提出更优雅的解决方案。

回答by TechyGypo

I was having the same problem using similar code to @TcKs and haven't been able to make any of these examples work for me. I got it working by using the LoadControlmethod of a UserControlas such:

我在使用与@TcKs 类似的代码时遇到了同样的问题,但无法使这些示例中的任何一个对我有用。我通过使用 a 的LoadControl方法让它工作UserControl

UserControl uc = new UserControl();
Control c = uc.LoadControl("newUserControl.ascx");
c.RenderControl(myWriter);