【问题标题】:Exception thrown when rendering a dynamic label WebControl with the AssociateControlID使用 AssociateControlID 呈现动态标签 WebControl 时引发异常
【发布时间】:2016-08-15 20:42:24
【问题描述】:

调用在运行时动态构建 HTML 元素并将呈现的元素作为字符串返回的 Web 服务时出现异常。

RenderControl()方法调用出现如下错误:

System.Web.HttpException:找不到与标签“lblCertificate”关联的 ID 为“txtCertificate”的控件。

StringWriter stringWriter = new StringWriter();
HtmlTextWriter writer = new HtmlTextWriter(stringWriter);

// Create System.Web.UI.WebControls.Panel (container)
Panel pnlFRow1 = new Panel();
pnlFRow1.CssClass = "f-row";

// Create System.Web.UI.WebControls.Textbox
TextBox txtCertificate = new TextBox();
txtCertificate.ID = "txtCertificate";
txtCertificate.CssClass = "f-input f-input-full";

// Create System.Web.UI.WebControls.Label
Label lblCertificate = new Label();
lblCertificate.ID = "lblCertificate";
lblCertificate.CssClass = "f-label f-label-full";
lblCertificate.AssociatedControlID = txtCertificate.ID;
lblCertificate.Text = "Certificate:";
Panel pnlCertificate = new Panel();
pnlCertificate.CssClass = "f-label f-label-full";

// Binding child controls to parent controls
pnlFRow1.Controls.Add(lblCertificate);
pnlFRow1.Controls.Add(pnlCertificate);
pnlCertificate.Controls.Add(txtCertificate);

// Render control
pnlContent.RenderControl(writer);

// Return rendered HTML
return writer.InnerWriter.ToString();

我尝试将pnlFRow1.Controls.Add(lblCertificate); 行放在pnlCertificate.Controls.Add(txtCertificate); 行之后,认为这可能是顺序很重要的问题,但这会导致相同的错误。

AssociatedControlID 属性是必须具备的,以便将Label WebControl 呈现为实际的<label> 元素,并且必须在输入控件之前显示。

【问题讨论】:

    标签: c# .net rendering web-controls


    【解决方案1】:

    一种方法是继承 Label 类,并将 RenderBeginTag 方法替换为您更喜欢的方法。如果您嵌套 Label 类,它应该保留在本地上下文中并阻止它泄漏到应用程序的其余部分

    例如:

    public partial class _Default : Page 
    {
            public class Label : System.Web.UI.WebControls.Label {
            public string For = null;
            public override void RenderBeginTag(HtmlTextWriter writer) {
                AddAttributeIfExists(writer, "ID", ID);
                AddAttributeIfExists(writer, "For", For);
                writer.RenderBeginTag("Label");
            }
            private void AddAttributeIfExists(HtmlTextWriter writer, string name, string value) {
                if (!string.IsNullOrWhiteSpace(value))
                    writer.AddAttribute(name, value);
            }
        }
    
        protected void Page_Load(object sender, EventArgs e) {
            StringWriter stringWriter = new StringWriter();
            HtmlTextWriter writer = new HtmlTextWriter(stringWriter);
    
            Panel test = new Panel() { ID = "PanelTest" };
    
            TextBox txtCertificate = new TextBox() { ID = "txtCertificate" };
            Label lblCertificate = new Label() { ID = "lblCertificate", Text = "Certificate", For = txtCertificate.ClientID };
    
            test.Controls.Add(lblCertificate);
            test.Controls.Add(txtCertificate);
    
            test.RenderControl(writer);
            string teststring = writer.InnerWriter.ToString();
        }
    }
    

    注意:您现在可以使用自定义的For 属性,而不是使用AssociatedControlId,它会做同样的事情。另请注意 Label 类是如何嵌套在您的页面类中的,因此它不会干扰其他页面。

    不幸的是,正如我们在此答案的第一个版本中发现的那样,如果您尝试在没有 AssociatedControlId 的情况下使用 .Attributes["for"],.NET 会将 <Label> 转换为 <span>,所以上面的示例应该得到围绕这个。

    【讨论】:

    • 添加属性的唯一问题是Label WebControl 不会呈现为<label> 元素
    • 嗯,奇怪,如果没有 AssociatedControlID,.NET 会将其更改为 span 标签。另一种选择是在本地扩展 Label webcontrol,请参阅我的更新答案
    • 你在这里做了一些事情,唯一的问题是它不再呈现任何其他属性。例如,您的示例中的 ID 属性未呈现。
    • 您可以在覆盖中添加 ID 属性。问题是base.RenderBeginTag()是添加属性的方法,但这也是添加<span>标签而不是<label>标签的方法,所以如果我们想保证我们不能调用它'总会得到<label>。查看我的更新答案
    • 我理解您的方法,但必须有更好的方法来动态检索这些属性的值,而无需指定属性的名称。
    猜你喜欢
    • 2011-01-11
    • 2011-01-12
    • 2020-08-12
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 2013-10-09
    • 2018-09-13
    • 1970-01-01
    相关资源
    最近更新 更多