PradoSoft

Pt:Escrevendo novos Controles

From PRADO Wiki

Voltar à página principal

Contents

Escrevendo novos Controles

Escrever novos controles é freq&uêntemente desejado por programadores avançados, por que eles precisam reaproveitar o código escrito para complexas apresentações e interações com usuários.

Em geral, tem duas maneiras de escrever novos controles: Composição de controles existentes e extender a classe de controles existentes. Todos reequerem que o novo controle herde a classe TControl ou suas classes-filho.


Composição de Controles já existentes

Esta é a maneira mais fácil para criar novos controles. Envolve principalmente a instanciação de controles já existentes, a configuração deles e fazê-los componentes constituídos. As propriedades dos componentes constituídos são explicadas completamente em Sub-Propriedades do Componente.

Pode-se compor um novo controle de duas maneiras. Uma é extendendo o "TCompositeControl" e sobrescrevendo o método "TControl::createChildControls()". A outra é extender o "TTemplateControl" ou suas classes-filho e escrever um template de controle. A última é a maneira mais fácil de usar e pode organizar no layout os componentes constituídos de modo mais intuitivo, enquanto a primeira é mais eficiente, pois não há interpretação de template.

Por exemplo, nós mostraremos como criar um textbox com um label que chamaremos "LabeledTextBox" usando as duas maneiras. O "labeledTextBox" mostra um label à esquerda de um textbox. Nós queremos reusar os componentes "TLabel" e "TTextBox" do PRADO para realizar esta tarefa.

Composição por Templates

Nós precisamos de dois arquivos: um arquivo de classe de controle chamado "LabeledTextBox.php" e um arquivo de template de controle chamado "LabeledTextBox.tpl". Ambos precisam estar no mesmo diretório.

Como se estivéssemos criando uma página PRADO, nós podemos facilmente escrever o conteúdo em um arquivo de template de controle.

<com:TLabel ID="Label" ForControl="TextBox" />
<com:TTextBox ID="TextBox" />

O template acima especifica um controle "TLabel" chamado "Label" e um controle "TTextBox" chamado "TextBox". Nós pretendemos expor estes dois controles. Isto pode ser feito por definições de propriedades de cada controle dentro do arquivo de classe "LabeledTextBox". Por exemplo, nós podemos definir a propriedade "Label" como a seguir:

class LabeledTextBox extends TTemplateControl {
    public function getLabel() {
        $this->ensureChildControls();
        return $this->getRegisteredObject('Label');
    }
}

No código acima, a chamada do método "ensureChildControls()" certifica que tanto o label quanto o textbox estão criados (à partir do template) quando a propriedade "Label" é acessada. A propriedade "TextBox" pode ser implementada da mesma maneira.

Ver Exemplo Ver Código

Composição por Sobreposição do método "createChildControls()"

Para compor controles simples como o "LabeledTextBox", é melhor que se crie extendendo o "TCompositeControl" e sobrescrevendo o método "createChildControls()", pois isto não requer a interpretação de templates, economizando o tempo que isto levaria.

O Código completo para o "LabeledTextBox" é mostrado abaixo:

class LabeledTextBox extends TCompositeControl {
    private $_label;
    private $_textbox;
    protected function createChildControls() {
        $this->_label=new TLabel;
        $this->_label->setID('Label');
        // add the label as a child of LabeledTextBox
        $this->getControls()->add($this->_label);
        $this->_textbox=new TTextBox;
        $this->_textbox->setID('TextBox');
        $this->_label->setForControl('TextBox');
        // add the textbox as a child of LabeledTextBox
        $this->getControls()->add($this->_textbox);
    }
    public function getLabel() {
        $this->ensureChildControls();
        return $this->_label;
    }
    public function getTextBox() {
        $this->ensureChildControls();
        return $this->_textbox;
    }
}

Ver Exemplo Ver Código.

Utilizando o "LabeledTextBox"

Para utilizar o Controle "LabeledTextBox", primeiro nós precisaremos incluir o arquivo de classe correspondente. Então no arquivo de template da página, nós podemos escrever as linhas abaixo:

<com:LabeledTextBox ID="Input" Label.Text="Username" />

No código acima, "Label.Text" é uma sub-propriedade do "LabeledTextBox", que refere-se à propriedade "Text" da propriedade "Label". Para maiores detalhes do uso do "LabeledTextBox", veja os exemplos nos links acima.


Extendendo controles já Existentes

Extendento controles já existentes é como a herança de classe convencional do PHP. Isto permite aos desenvolvedores customizar classes de controles existentes, alterando suas propriedades, métodos, eventos, ou criando outros novos.

A dificuldade da tarefa depende de classes existentes precisam ser customizadas. Por exemplo, uma simples tarefa pode customizar um controle "TLabel", para ele exibir o texto em vermelho, por padrão. Isto envolve meramente a atribuição da propriedade "ForeColor" para "red" no construtor. Uma tarefa difícil é criar controles que disponibilizem funcionalidades inovadoras. Normalmente, isto requer que novos controles extendam classes de controle de "baixo-nível" como o "TControl" ou "TWebControl".

Nesta seção, nós introduziremos principalmente as classes de controle "TControl" e "TWebControl", mostrando como elas podem ser customizadas. Nós também introduziremos como escrever controles com funcionalidades específicas, como carregar dados postados, interpretá-los e realizar a ligação dos dados (databinding) com a fonte de dados (datasource).


Extendendo TControl

O "TControl" é uma classe de base de todas as classes de controle. Dois métodos são de maior importância em classes derivadas:

  • "addParsedObject()" - este método é invocado para cada componente ou string de texto contendo tags de especificação de componentes em um template. Por padrão, os componentes encapsulado e textos em string são adicionados dentro da coleção "Controls" do controle. Controles derivados podem sobrepor este método para processamentos especiais sobre o conteúdo encapsulado. Por exemplo, o "TListControl" só aceita componentes "TListItem" para encapsular junto com seu tag de componente, e estes componentes são adicionados na coleção "Items" do "TListControl".
  • "render()" - este método gera o controle. Por padrão, ele gera itens na coleção "Controls". Controles derivados podem sobrepor este método para dar uma apresentação customizada.

Outras propriedades e métodos importantes são:

  • "ID" - uma string única identificando o controle de todos os outros controles de mesmo nome de recipiente. Caso esta propriedade não seja preenchida, ela será gerada automaticamente pelo sistema.
  • "UniqueID" - um ID completo que diferencia o controle de todos os outros na hierarquia da página. Ele pode ser usado para localizar um controle na hierarquia da página pela chamada do método "TControl::findControl". Controles de entrada de usuário frequentemente usam-na como valor do atributo "name" do elemento input do HTML.
  • "ClientID" - semelhanete ao "UniqueID", exceto que ele é principalmente usado para apresentação e usado normalmente como valor do atributo ID do elemento input do HTML. Não confie no formato explícito de "ClientID".
  • "Enabled" - se este controle está habilitado. Note que, em alguns casos, se um dos controles-pai estiverem desabilitados, o controle deverá também ser tratado como desabilitado, mesmo que sua propriedade "Enabled" estiver como verdadeiro (true).
  • "Parent" - o controle-pai deste controle. O controle-pai está sendo carregado se a gerar este controle e onde colocar este resultado gerado.
  • "Page" - a página que contém este controle.
  • "Controls" - a coleção de todos os controles-filho, incluindo textos estáticos existentes entre eles. Ele pode ser usado como um array, pois ele implementa a interface "Transversable". Para adicionar um filho ao controle, simplesmente insira-o na coleção "Controls" na posição apropriada.
  • "Attributes" - coleção de atributos customizados. Isto é útil para permitir aos usuários especificar atributos de elementos de saída HTML que não são cobertos pelas propriedades do controle.
  • "getViewState()" e "setViewState()" - estes métodos são normalmente usados para definir propriedades que estão colocadas em viewstate.
  • "saveState()" e "loadState()" - estes dois métodos podem ser sobrepostos para fornecer o estado salvo e carregado da etapa anterior.
  • Ciclo-de-vida dos Controles - Como páginas, os controles também possuem ciclo-de-vida. Cada controle submete-se ao ciclo-de-vida a seguir na seguinte ordem: constructor, "OnInit()", "OnLoad()", "onPreRender()","render()" e "onUnLoad()". Maiores detalhes podem ser encontrados na seção Páginas.

Extendendo TWebControl

O "TWebControl" é principalmente usado como base dos controles que representam elementos HTML. Ele fornece um conjunto de propriedades que são comuns entre elementos HTML. Ele quebra o TControl::render() nos seguintes métodos que são mais apropriados para gerar um elemento do HTML:

  • "addAttributesToRender()" - adiciona atributos ao elemento HTML que será gerado. Este método é normalmente sobreposto por classes derivadas por que elas normalmente possuem atributos diferentes a serem gerados.
  • "renderBeginTag()" - gera a tag de abertura HTML.
  • "renderContents()" - gera o conteúdo encapsulado dentro do elemento HTML. Por padrão, ele exibe os itens da coleção "Controls" do controle. Classes derivadas podem sobrepor este método para gerar conteúdos customizados.
  • "renderEndTag()" - gera a tag de fechamento HTML.

Quando está gerando a tag de abertura HTML, o "TWebControl" chama o "getTagName()" para obter o nome da Tag. Classe derivadas podem sobrepor este método para gerar nomes de tags diferentes.

Criando Controles com funcionalidades especiais

Se um controle precisa responder a eventos no lado do cliente e transferí-los para eventos no lado do servidor (chamados eventos postback), como um "TButton", ele tem que implementar a interface "IPostBackEventHandler".

Se um controle precisa estar apto a carregar dados postados, como um "TTextBox", ele precisa implementar a interface "IPostBackDataHandler".

Se um controle precisa receber dados de alguma fonte de dados externa, ele pode extender o "TDataBoundControl". O "TDataBoundControl" implementa as proprieades e métodos básicos que são necessários para o preenchimento de dados pela ligação de dados (databinding). De fato, controles como "TListControl", "TRepeater" e "TDataGrid" são todos derivados deste.

Personal tools
Your user name:

Your password:

MediaWiki