我正在编写一个继承自CompositeControl的小型ASP.Net自定义控件。该控件只是一个面板,其中包含两个子面板,每个子面板上都有一个标签。渲染时,我在HTML源代码中看到我的自定义控件的第一个子控件获得了两个id属性 - 第一个是自定义控件本身的id,第二个是我分配给第一个子控件的ID属性。为什么会这样?
代码:
[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();
_MessageHeaderLabel.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);
}
}
ASPX页面中的用法:
<cc:MessageBox ID="ctlMessageBox" runat="server" />
HTML输出:
<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>
答案 0 :(得分:4)
您可以通过完全删除RenderContents
方法来解决此问题 - 请勿将其替换为任何内容。默认情况下,复合控件呈现其所有子控件。如果这样做,您的控件将生成干净的标记:
<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>
正如您所指出的,AddAttributesToRender
方法是罪魁祸首 - 它是一种方便的方法,可以呈现所有顶级控件的属性(当前上下文是否为顶级控件)。你可以这么称呼的唯一原因是你自己完全控制了渲染过程,并希望在一个语句中渲染顶层控件的所有属性。
答案 1 :(得分:-1)
这是ASP.NET分配自定义控件的ID。如果将自定义控件包装在Div或Span中(在自定义控件代码本身内,而不是在标记中),则会将ID分配给该ID而不是第一个内部“控件”。
这样的事情:
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();
}