Pensando nisso os desenvolvedores do Asp.Net criaram uma classe base para este tipo de controles, a CompositeControl.
A utilização da CompositeControl faz o trabalho de criar controles complexo uma tarefa bastate fácil, porém algumas vezes você precisa herdar de um controle que não é filho de CompositeControl, por exemplo customizar um Textbox.
Implementar as funcionalidades já presentes na ComposisteControle pode ser feita implementando alguns métodos.
- CreateChildControls: Responsável por criar os controles filhos e adicioná-los à lista de controles filhos (this.Controls). O ideal é que a criação de controles filhos seja controlada dentro desta função, evitando que o código fique espalhado.
- RenderChildren(HtmlTextWriter writer): Responsável por renderizar os controles filhos, o modo de operação padrão é simplesmente chamar o método RenderControl para cada um dos itens da lista (this.Controls).
- Render(HtmlTextWriter writer): Este método apenas deve efetuar uma chamada ao método EnsureChildControls() e depois pode simplesmente chamar o método da classe base (base.Render(writer);)
- EnsureChildControls: Este método não deve ser implementado, porém ele tem um papel fundamental. Seu objetivo é verificar a propriedade ChildControlsCreated e caso seja false, executar a chamada ao método CreateChildControls.
- ChildControlsCreated: Sempre que for necessário recriar os itens filhos, o método ideal é setar essa propridade como false e posteriormente efetuar uma chamada ao método EnsureChildControls
public class LabeledTextBox : WebControl
{
private Label _nameLabel;
private TextBox _field;
[Browsable(true)]
public Label NameLabel
{
get
{
EnsureChildControls();
return _nameLabel;
}
}
public TextBox Field
{
get
{
EnsureChildControls();
return _field;
}
}
protected override void CreateChildControls()
{
this.Controls.Clear();
base.CreateChildControls();
_nameLabel = new Label();
_nameLabel.ID = this.ID + "_Label";
_field = new TextBox();
_field.ID = this.ID + "_Textbox";
this.Controls.Add(_nameLabel);
this.Controls.Add(_field);
}
protected override void Render(HtmlTextWriter writer)
{
EnsureChildControls();
base.Render(writer);
}
protected override void RenderChildren(HtmlTextWriter writer)
{
_nameLabel.RenderControl(writer);
writer.WriteBreak();
_field.RenderControl(writer);
}
}
Esta classe é muito simples e não encapsula muito bem os controles, o ideal seria nunca exibir os controles filhos através de propridades públicas pois assim classes clientes podem se apoiar nas interfaces dos controles exibidos nas propriedades.
Sendo assim ao exibir os controles da maneira apresentada o controle fica preso e poderá somente utilizar controles de classes que descendem de Label e Textbox.