ASP.Netカスタムコントロールが最初の子コントロールで2つのid属性をレンダリングするのはなぜですか?

StackOverflow https://stackoverflow.com/questions/1601039

質問

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();
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top