开发者

Why does my ASP.Net custom control render two id attributes on my first child control?

开发者 https://www.devze.com 2022-12-09 15:38 出处:网络
I\'m writing a small ASP.Net custom control inheriting from CompositeControl.The control is just a panel containing two subpanels with a label in each subpanel.When rendered, I am seeing in the HTML s

I'm writing a small ASP.Net custom control inheriting from CompositeControl. The control is just a panel containing two subpanels with a label in each subpanel. When rendered, I am seeing in the HTML source that the first child control of my custom control gets two id attributes - the first being the id of the custom control itself and the second being the ID property I assign to the first child control. Why is this happening?

Code:

[ToolboxData("<{0}:MessageBox runat=server></{0}:MessageBox>")]
public class MessageBox : CompositeControl {

    private Panel _MessageHeaderContainer = null;
    private Label _MessageHeaderLabel = null;
    private Panel _MessageDetailsContainer = null;
    private Label _MessageDetailsLabel = null;

    protected override HtmlTextWriterTag TagKey {
        get {
            return HtmlTextWriterTag.Div;
        }
    }

    protected override void CreateChildControls() {

        // Message header area.
        _MessageHeaderContainer = new Panel();
        _MessageHeaderContainer.ID = "HeaderContainer";
        _MessageHeaderContainer.CssClass = "__MessageBox_Container";
        this.Controls.Add(_MessageHeaderContainer);

        // Message header text.
        _MessageHeaderLabel = new Label();
        _Message开发者_开发技巧HeaderLabel.ID = "HeaderLabel";
        _MessageHeaderLabel.Text = "[ Header ]";
        _MessageHeaderContainer.Controls.Add(_MessageHeaderLabel);

        // Message details area.
        _MessageDetailsContainer = new Panel();
        _MessageDetailsContainer.ID = "DetailsContainer";
        this.Controls.Add(_MessageDetailsContainer);

        // Message details text.
        _MessageDetailsLabel = new Label();
        _MessageDetailsLabel.ID = "DetailsLabel";
        _MessageDetailsLabel.Text = "[ Details ]";
        _MessageDetailsContainer.Controls.Add(_MessageDetailsLabel);

    }

    protected override void RenderContents(HtmlTextWriter output) {
        AddAttributesToRender(output);

        // Render the box.
        _MessageHeaderContainer.RenderControl(output);
        _MessageDetailsContainer.RenderControl(output);
    }
}

Usage in ASPX page:

<cc:MessageBox ID="ctlMessageBox" runat="server" />

HTML output:

<div id="ctl00_ctl00_ctlMessageBox">
    <div id="ctl00_ctl00_ctlMessageBox" id="ctl00_ctl00_ctlMessageBox_HeaderContainer" class="__MessageBox_Container">
        <span id="ctl00_ctl00_ctlMessageBox_HeaderLabel">[ Header ]</span>
    </div><div id="ctl00_ctl00_ctlMessageBox_DetailsContainer">
        <span id="ctl00_ctl00_ctlMessageBox_DetailsLabel">[ Details ]</span>
    </div>
</div>


You can fix this by removing the RenderContents method entirely - don't replace it with anything. By default, composite controls render all their child controls. If you do this, your control produces clean markup:

<div id="test">
    <div id="test_HeaderContainer" class="__MessageBox_Container">
     <span id="test_HeaderLabel">[ Header ]</span>
    </div>
    <div id="test_DetailsContainer">
     <span id="test_DetailsLabel">[ Details ]</span>
    </div>
</div>

As you've noted, the AddAttributesToRender method is the culprit - it's a convenience method renders all the top-level control's attributes (whether the current context is the top-level control or not). The only reason you would call this is if you were taking full control of the rendering process yourself and wanted to render all the attributes for the top-level control in a single statement.


This is the ID ASP.NET assigns the Custom Control as a whole. If you wrap your Custom Control in a Div or Span (within the Custom Control code itself, not in the markup) the ID will be assigned to that instead of your first inner "control".

Something like this:

protected override void Render(HtmlTextWriter writer)
{
  AddAttributesToRender(writer);

  //must render tag or first inner control will get two IDs
  writer.RenderBeginTag(HtmlTextWriterTag.Span);

  //render child controls here...

  writer.RenderEndTag();
}
0

精彩评论

暂无评论...
验证码 换一张
取 消