Por que o meu controle personalizado ASP.Net prestam dois atributos id no meu primeiro controle filho?

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

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>
Foi útil?

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();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top