Por que o meu controle personalizado ASP.Net prestam dois atributos id no meu primeiro controle filho?
-
05-07-2019 - |
Pergunta
Eu estou escrevendo um pequeno controle personalizado ASP.Net herdando de CompositeControl. O controlo é apenas um painel contendo dois subpainéis com um rótulo em cada subpainel. Quando renderizado, eu estou vendo em HTML que o primeiro controle filho do meu controle personalizado recebe dois atributos id - sendo o primeiro o ID do próprio controle personalizado eo segundo é o ID de propriedade atribuir ao primeiro controle filho. Por que isso está acontecendo?
Código:
[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);
}
}
Uso em ASPX página:
<cc:MessageBox ID="ctlMessageBox" runat="server" />
HTML de saída:
<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>
Solução
Você pode corrigir isto removendo o método RenderContents
inteiramente - não substituí-lo com qualquer coisa. Por padrão, controles compostos tornar todos os seus controles filho. Se você fizer isso, seu controle produz marcação limpa:
<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>
Como você observou, o método AddAttributesToRender
é o culpado - é um método de conveniência torna todos os atributos do controle de nível superior (se o contexto atual é o controle de nível superior ou não). A única razão que você chamaria isso é se você estivesse tomando o controle total do processo de renderização-se e queria tornar todos os atributos para o controle de nível superior em uma única instrução.
Outras dicas
Este é o cessionários ID ASP.NET o controle personalizado como um todo. Se você quebrar o seu controle personalizado em um div ou span (dentro do próprio, não na marcação código de controle personalizado), o ID será atribuído a que, em vez de seu primeiro "controle" interno.
Algo parecido com isto:
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();
}