ASP.Netカスタムコントロールが最初の子コントロールで2つのid属性をレンダリングするのはなぜですか?
-
05-07-2019 - |
質問
CompositeControlを継承する小さなASP.Netカスタムコントロールを作成しています。コントロールは、各サブパネルにラベルが付いた2つのサブパネルを含む単なるパネルです。レンダリングすると、HTMLソースで、カスタムコントロールの最初の子コントロールが2つのid属性を取得することがわかります。1つ目はカスタムコントロール自体のIDで、2つ目は最初の子コントロールに割り当てる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>
解決
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つのステートメントでトップレベルコントロールのすべての属性をレンダリングしたい場合です。
他のヒント
これは、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();
}
所属していません StackOverflow