Introdução
O ASP.NET trouxe um novo mecanismo para substituir o comando #Include
muito utilizado no asp para fazer blocos de códigos separados e
depois sair replicando em todas as paginas. Um exemplo muito comum
era separar o html comum a todas as paginas, tipo o cabeçalho e
colocar em apenas uma pagina, depois por meio do #Include colocava-se
em todas as paginas essa chamada. Mas mantendo um único código no
arquivo do #Include.
Essa pratica pode ser até considerada na época uma forma
primitiva de fazer um componente, pois o código se concentra-se
em um único ponto e era replicado. Elaborei esse artigo com
objetivo de elucidar as principais duvidas sobre User Controls e
trazer subsídios para se aposentar de vez o conceito anterior de #Include.
|
User
Control (*.ascx)
O
componente rápido e fácil de ser implementado oferecido pelo ASP.NET com objetivo de
substituir os arquivos de #Include, oferecendo as mesmas facilidades
anteriores com as novas vantagens do .NET, agora cada controle de
usuário pode ter seus próprios eventos, propriedades e é compilado
dentro da DLL da mesma forma que as paginas (*.aspx). Dentro de uma
paginas ASP.NET você pode interceptar os eventos disparados pelo
controle de forma que dentro do servidor de forma programática
você pode implementar um tratamento para um clique em um botão no
controle de usuário.
Outros pontos chaves:
-> Com User Control você pode fragmentar sua pagina de forma que
consiga colocar no cache do ASP.NET apenas aquele bloco da pagina que
é processado dentro do controle. Cache é outro novo recurso do ASP.NET
que similar ao "Cache do Browser" ocorre no servidor ao
invéz de acontecer no cliente. Com isso um controle que tem um
processamento pesado por ficar no Cache e ser oferecido para todos
Usuários da aplicação.
-> Cada controle adicionado a pagina tem seu processamento
independente, mesmo sendo iguais, cada evento disparado dentro do
controle será processamento pelo mesmo.
-> Orientado a objeto, possui uma classe que faz herança de System.Web.UI.UserControl
de forma que a mesma possa obter todas funcionalidades básica para
permitir o funcionamento do controle dentro do ambiente ASP.NET
.
Para adicionar um User Control ao seu projeto vá no Solution
Explorer>Projeto>Add>Add Web User Control conforme Figura
01.
Figura 01 - Adicionando User Control
O
Próximo passo agora é informar um nome para o mesmo. Minha sugestão
seria uc_teste.ascx conforme Figura 02. Em minhas aplicações
todos User Controls utilizo o padrão começado por uc_?????.ascx
Figura 02 - Informando nome do arquivo para User Control
Após
adicionando ao projeto, você vai observar que o UserControl não
possui possui o padrão de layout GridLayout do aspx e apenas utiliza
o padrão FlowLayout. A diferença entre esses padrões é que o
GridLayout permite alinhamento exato dos objetos na tela.
O UserControl é muito semelhante a uma pagina *.aspx ele possui dois
arquivos. No nosso caso (uc_teste.ascx e uc_teste.ascx.vb) sendo que
dentro do *.ascx fica o código html, contendo formatação html e
outros webcontrols. E dentro do uc_teste.ascx.vb fica o seu código em
si, esse código que vai ser compilado e adicionado dentro da DLL na
pasta \bin de seu projeto. Portanto você não precisa mandar o
arquivo .vb para o servidor de produção.
Uma rápida visualização no arquivo uc_teste.ascx teríamos o
trecho de código abaixo:
<%@ Control
Language="vb" AutoEventWireup="false"
Codebehind="uc_teste.ascx.vb" Inherits="treinamento.uc_teste" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
A diretiva @Control indica que esse arquivo ascx é um UserControl.
Esse tipo de controle não pode conter nesse arquivo tags <html><body></body></html>
e somente o código html, pois essas tags já estarão presentes nas
paginas *.aspx
Uma
visualização do arquivo uc_teste.ascx.vb teríamos o trecho
de código mostrado na Figura 03.
Figura 03 - Conteúdo arquivo uc_teste.ascx.vb
Observando ainda a Figura 03 observaremos mais algumas
semelhanças com uma pagina (*.aspx), sendo que o controle também
possui uma classe própria que faz herança de System.Web.UI.UserControl
de forma que possa obter todas funcionalidades para funcionar como um
User Control. E outro evento já conhecido é o Page_Load que é
disparado em uma pagina toda vez que ela é processada (Vai e volta no
servidor). Sendo assim dentro do controle você pode fazer
implementações utilizando esse evento deixando restrito ao escopo
desse controle. Lembre apenas que primeiro é disparado o Page_Load na
pagina (*.aspx) e depois que é disparado nos controles.
Até
esse momento já verificamos diversos itens no User Control e você
já deve ter percebido que o papel dele dentro da estrutura do ASP.NET
é oferece muito mais facilidades do que um simples #Include. Lembre
também que User
Control somente podem ser testados dentro de paginas *.aspx e não
chamados diretamente pela url http://localhost/treinamento/uc_teste.ascx,
você deve inserir em uma pagina (*.aspx)
e depois testar utilizando essa pagina.
Dica:
Como já visto o User Control possui estrutura similar a uma pagina
web, portanto esteja a vontade para utilizar todos recursos de
programação disponíveis, tal como BreakPoint para depurar
UserControl. Observe na Figura 04.
Figura 04 - Inserindo BreakPoint no UserControl
|
Primeiro
Teste |
Insira 01(um) Button e 01 (Label) conforme Figura
5. Depois clique em <HTML> para ver o conteúdo html desse
controle conforme Figura 6.
|
Figura
05 - Montando layout para teste
|
Figura
06 - Observando html gerado dentro do controle.
Agora que já observou na Figura 06 o html criado efetue
dois cliques no botão para irmos ao código(Codebehind).
O resultado é apresentado na Figura 07. Observe o método btTeste_Click
que vai tratar o clique do usuário neste botão dentro do controle. Ou
seja essa codificação será feita pelo controle. Para continuar
complete o código conforme a Listagem 01.
Figura
07 - Código gerando pelo Visual Studio dentro do arquivo (uc_teste.ascx.vb)
|
Listagem 01 - Código para botão btTeste
Public Class
uc_teste
Inherits
System.Web.UI.UserControl
Private
Sub Page_Load(ByVal
sender As System.Object, _
ByVal e As
System.EventArgs) Handles MyBase.Load
End
Sub
Private
Sub btTeste_Click(ByVal
sender As SystemObject, _
ByVal
e As System.EventArgs) Handles
btTeste.Click
"///////////////////////////////////////////////
"Ao
clicar no botão imprimir no Label o valor
"informado
na caixa de texto.
"///////////////////////////////////////////////
Me.lblTeste.Text
= Me.txtTeste.Text
End
Sub
End Class |
Feito isso, no
solution explorer>projeto>Add>Add Web Form e adicione uma
pagina (paginadeteste.aspx). Feito isso arraste diretamente do
solution explorer>projeto>uc_teste.ascx para essa nova pagina.
Automaticamente o Visual Studio vai adicionar esse controle na pagina
conforme Figura 08.
Figura 08 - Inserido User Control na pagina
Após o Build do projeto você já pode tentar acessar essa pagina http://localhost/treinamento/paginadeteste.aspx
e vai obter o resultado da Figura 09. Digite algo na caixa de
texto e veja o resultado.
Figura 09
- Pagina de Teste
|
Feito os testes retorne a paginadeteste.aspx e visualize o <HTML>
localize a TAG <%@ Register TagPrefix="uc1" TagName="uc_teste"
Src="uc_teste.ascx" %>
. Essa referencia está indicando que o controle está inserido
nessa pagina. Retorne essa pagina ao modo normal e arraste novamente
pelo solution explorer o usercontrol para essa mesma pagina, vai ser
criado uma nova cópia. Realize o Build e teste, ao clicar no primeiro
botão vai mudar apenas o conteúdo do primeiro controle. Ou seja
apesar de serem idênticos eles tem processamentos separados. Confira
a Figura 10.
Figura 10
- Inserindo dois controles na mesma pagina
|
|
Carregando dinamicamente
na pagina |
Neste
primeiro exemplo aprendemos a arrastar via interface do ide (Visual
Studio) o controle para pagina. Agora vamos ver como carregar usando
código pois caso você tenha essa necessidade é possível de se
fazer. Para isso insira uma nova pagina (paginadeteste2.aspx) e no
evento Page_Load adicione o código conforme a Listagem 02.
|
Listagem
02 - Carregando dinamicamente controle na pagina
Public Class
paginadeteste2
Inherits
System.Web.UI.Page
Private
Sub Page_Load(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles MyBase.Load
Me.Page.FindControl("Form1").Controls.Add(LoadControl("uc_teste.ascx"))
End
Sub
End Class |
|
Interceptando
User Control |
Durante
sua implementação pode ser que seja necessário na sua pagina obter
um valor que foi informado dentro de um controle ou mesmo alterar
um valor. Tal como interceptar um evento gerado e tomar a ação
dentro da pagina. Para este caso adicione um controle (uc_interceptando.ascx)
e uma nova pagina para teste (paginadeteste3.aspx). Veja o layout do
controle na Figura 11.
Figura 11 - Layout do controle
Feito isso devemos fazer fazer com que esse controle disponibilize
meios para que possa expor os valores da caixa de texto e expor o
evento que vai ser disparado quando o usuário clicar nesse botão.
Faremos isso utilizando Property e Event para expor as propriedades
para caixa de texto e o evento do botão cadastrar. Para ver como
implementar visualize a Listagem 03.
|
|
Listagem 03 - Implementando Property e Event dentro classe
uc_intercepdando
Public Class
uc_interceptando
Inherits
System.Web.UI.UserControl
Private
Sub Page_Load(ByVal
sender As System.Object,_
ByVal e As
System.EventArgs) Handles MyBase.Load
End
Sub
Private
Sub btCadastro_Click _
(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) Handles
btCadastro.Click
"//////////////////////////////////////////
"Disparando
evento btCadastro_EventoClick
"Esse
evento será tratado na pagina aspx
"//////////////////////////////////////////
RaiseEvent
btCadastro_EventoClick(sender, e)
End Sub
"Expondo propriedade
para alterar txtNome
"Ou obter valor de
txtNome
Public Property ptxtNome() As
String
Get
Return
Me.txtNome.Text
End Get
Set(ByVal
Value As String)
Me.txtNome.Text
= Value
End
Set
End
Property
"Expondo
propriedade para alterar txtEmail ou
"Ou obter valor de
txtEmail
Public Property ptxtEmail() As
String
Get
Return
Me.txtEmail.Text
End Get
Set(ByVal
Value As String)
Me.txtEmail.Text
= Value
End
Set
End
Property
"////////////////////////////////////////
"Expondo evento
btCadastro_EventoClick
"-->Botão
Cadastrar
"///////////////////////////////////////
Public Event
btCadastro_EventoClick _
(ByVal
sender As System.Object, _
ByVal e As
System.EventArgs)
End Class
|
Utilizando dos
conceitos de OOP estamos criando duas propriedades (ptxtNome,ptxtEmail) que alteraram ou retornam os valores das
respectivas caixas de textos e criamos um evento chamado de
btCadastro_EventoClick que vai expor externamente a essa classe o
evento clique do botão btCadastro. Quando o usuário clicar no botão
btCadastro implementamos o código "RaiseEvent
btCadastro_EventoClick(sender, e)"
que
repassa esse evento interno no controle para o btCadastro_EventoClick
que pode ser acessado externamente.
Arraste agora esse controle para a pagina paginadeteste3.aspx depois
adicione 01 (um) Panel, 01(um) CheckBox (ID=ckAlteraLer,Text=Altera/Ler),
01(um) TextBox(ID=txtProcessa), 01(um) RadioButtonList (ID=rdAcao,Itens=Nome
e Email ), 01(um) Button (ID=btProcesa) e monte o lauyout conforme Figura
12.
Figura 12 - Layout paginadeteste3.aspx
Qualquer dificuldade para montar o layout acima copie o código da
Listagem 04 e adicione em sua pagina no modo <HTML> entre as
tags <form> </form>.
|
Listagem 04 - Layout em html da paginadeteste3.aspx
<uc1:uc_interceptando
id="Uc_interceptando1" runat="server">
</uc1:uc_interceptando>
<asp:Panel
id="pn001"
style="Z-INDEX:
101; LEFT: 8px;
POSITION: absolute; TOP: 176px"
runat="server"
Width="368px"
Height="144px"
BorderStyle="Outset">
Alterando dados no UserControl<BR>Digite
aqui:<BR>
<asp:RadioButtonList
id="rdAcao"
runat="server"
RepeatDirection="Horizontal">
<asp:ListItem
Value="Nome"
Selected="True">Nome</asp:ListItem>
<asp:ListItem
Value="Email">Email</asp:ListItem>
</asp:RadioButtonList>
<asp:TextBox
id="txtProcessa"
runat="server"></asp:TextBox><BR>
<asp:CheckBox
id="ckAlteraLer"
runat="server"
Text="Altera
/ Ler" Checked="True">
</asp:CheckBox><BR>
<asp:Button id="btProcessa" runat="server"
Text="Processa"></asp:Button>
</asp:Panel>
|
Definido o layout vamos agora a classe da pagina implementar o
código necessário para nosso teste. Dois cliques no formulário e
adicione o código conforme a Listagem 05.
|
Listagem 05 - Código para pagina (paginadeteste3.aspx.vb)
Public Class
paginadeteste3
Inherits
System.Web.UI.Page
"Adicionando Referencia
para UserControl
"Uc_interceptando1 que
foi adicionando
"a pagina. É muito
importante a linha
"Abaixo.
Protected
WithEvents Uc_interceptando1 As
uc_interceptando
Private Sub
Page_Load(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) Handles MyBase.Load
End
Sub
Private
Sub btProcessa_Click _
(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) Handles btProcessa.Click
If Me.ckAlteraLer.Checked
= True Then
"Alterar
dados no UserControl
If Me.rdAcao.Items(0).Selected = True
Then
Uc_interceptando1.ptxtNome
= Me.txtProcessa.Text
Else
Uc_interceptando1.ptxtEmail = Me.txtProcessa.Text
End
If
Else
"Ler
dados no UserControl
If Me.rdAcao.Items(0).Selected = True
Then
txtProcessa.Text
= Uc_interceptando1.ptxtNome
Else
Me.txtProcessa.Text =
Uc_interceptando1.ptxtEmail
End
If
End
If
End Sub
"//////////////////////////////////////////////////
"O
procedimento abaixo intercepta o evento
"disparado pelo
UserControl.
"///////////////////////////////////////////////
Private Sub btCadastra_UserControl _
(ByVal
sender As System.Object, _
ByVal
e As System.EventArgs) _
Handles
Uc_interceptando1.btCadastro_EventoClick
Response.Write("Usuário
clicou no botão Cadastra dentro do UserControl")
End
Sub
End Class |
Concluído o código de Listagem 05 você já pode testar sua pagina.
Nesse teste você vai ler um valor que está na caixa de texto ou modificar, tal
como interceptar o clique no botão "Cadastra".
|
Tornando
padrão em todas as paginas |
Agora
já sabemos que depois que você fizer seu controle, será necessário
arrastar para todas as paginas ou carrega-lo via código para que
possa ser utilizado. Agora vamos fazer uma modificação utilizando os
recursos do ASP.NET para que em qualquer pagina que for criada já
venha com um recurso do controle embutido, faremos isso por meio do
OOP. Criaremos uma nova classe baseada na classe System.Web.UI.Page
essa classe Page é a classe que contem todos os recursos para
funcionamento de uma pagina ASP.NET, portanto qualquer pagina para
funcionar precisa ter algum tipo de herança com essa classe.
Criaremos uma nova classe que vai herdar a Page de forma que qualquer
pagina que herdar de nossa classe possa funcionar como uma pagina no
ASP.NET. Dentro desa classe nova possa já vamos embutir nosso
controle e com isso utilizaremos essa classe para criar as novas
pagina. Com isso todas as novas paginas baseadas nessa classe já
terão embutidos nosso controle.
Para
iniciar vamos inserir um novo arquivo do tipo class conforme Figura
13 de o nome de clsPaginaPadrao.vb.
Figura 13 - Adicionando nova Classe ao projeto.
Modifique o arquivo clsPaginaPadrao.vb conforme o código apresentado na Listagem 6.
|
Listagem 6 - Criando uma classe herdada de
System.Web.UI.Page
Namespace
Mutex.Modelos
Public Class
clsPaginaPadrao
Inherits System.Web.UI.Page
#Region "#Expondo Controle"
Protected WithEvents uc_controle As uc_interceptando
#End Region
"Modificando metodo para já carregar
UserControl
Protected Overrides Sub
OnLoad(ByVal e As System.EventArgs)
uc_controle = DirectCast(LoadControl _
("uc_interceptando.ascx"), uc_interceptando)
Me.FindControl("Form1").Controls.Add(uc_controle)
MyBase.OnLoad(e)
End Sub
End Class
End
Namespace |
Completado a código da Listagem 6 adicione uma nova pagina em seu
projeto de nome paginadeteste4.aspx, depois dois cliques no formulário e
vamos código dessa pagina que deve está semelhante a Figura 14.
Figura 14 - Classe padrão de uma pagina recém criada.
Observe na Figura 14 que essa classe faz herança de System.Web.UI.Page,
a primeira coisa que temos que fazer é modificar essa linha para fazer herança
de nossa classe (Mutex.Modelos.clsPaginaPadrao)
que por vez já fez herança de System.Web.UI.Page e portanto tem as
mesmas funcionalidades dessa classe Page podendo tomar o lugar da mesma nesse
código. Portanto com uma simples modificação nessa linha, por meio da
herança nossa pagina já vai exibir o controle que está sendo carregado na
Classe Mutex.Modelos.clsPaginaPadrao. Confira essa
modificação e outras modificações adicionais que já fizemos na Listagem
7. Como nossa classe (Mutex.Modelos.clsPaginaPadrao) está carregando
o User Control (uc_interceptando.ascx) sabemos que o mesmo possui
propriedades e está expondo evento.
|
Listagem
7 - Modificando pagina (paginadeteste4.aspx) para herdar de Mutex.Modelos.clsPaginaPadrao
Public
Class paginadeteste4
Inherits Mutex.Modelos.clsPaginaPadrao
Private Sub Page_Load _
(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) _
Handles MyBase.Load
If
Not Me.Page.IsPostBack
Then
"Anterando
dados no User Control
MyClass.uc_controle.ptxtNome
= "Convidado"
MyClass.uc_controle.ptxtEmail
= "convidado@mutex.com.br"
End
If
End Sub
Private Sub clsPaginaPadrao_ucControle_Click _
(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) _
Handles uc_controle.btCadastro_EventoClick
Response.Write("<HR>")
Response.Write("O usuário
clicou no botão que está dentro do User Control.<BR>")
Response.Write("Nome:"
+ MyClass.uc_controle.ptxtNome +
"<BR>")
Response.Write("Email:"
+ MyClass.uc_controle.ptxtEmail + "<BR>")
Response.Write("<HR>")
End Sub
End
Class
|
Observando
o código da Listagem 7 você percebe que a única coisa que precisaria
fazer é mudar o Inherits, e fora isso não precisaríamos modificar mais
nada e já teríamos o controle na pagina. Mas para completar nosso conhecimento
sobre o assunto. Observe que estamos alterando valores do Controle e recebendo
eventos do mesmo em clsPaginaPadrao_ucControle_Click. Digamos que você
queria que todas as pagina já tenham o mesmo cabeçalho bastaria então você
seguir esses passos e já conseguiria isso rapidamente. Confira o resultado na Figura
15.
Figura
15 - Testando a pagina (paginadeteste4.aspx)
|
Adicionando ao Cache |
Agora
vamos aprender como colocar um controle no Cache do ASP.NET, que é
mais um novo recurso oferecido no ASP.NET que permite fragmentar a área
da pagina que vai ser armazenado dentro do servidor e recuperado de
forma rápida sem necessidade de reprocessamento. Um exemplo simples
poderia ser um DropDownlist que carrega dados de um banco de dados e
exibe os itens, digamos que essa base somente atualiza uma vez por
mês. Então você pode colocar esse controle no Cache e definir um
prazo de duração de 30 dias por exemplo. Quando a pagina carregar a
primeira vez o controle vai acessar o banco de dados, carregar os
dados e armazenar no cache. Os próximos usuários não precisarão
mais perder esse tempo, pois o ASP.NET vai recuperar esse controle do
cache. Ao final do prazo esse cache é Expirado.
Adicione um novo User control chamando de (uc_cache.ascx) e uma
nova pagina chamada de (paginadeteste5.aspx) monte o layout do
uc_cache conforme a Figura 16 e código conforme a Listagem
8.
Figura 16 - Layout de uc_cache.ascx
|
Listagem
8 - Exibindo Data/Hora em um Label dentro do Controle (uc_cache.ascx.vb)
Public Class
uc_cache
Inherits
System.Web.UI.UserControl
Private Sub
Page_Load _
(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) Handles MyBase.Load
"Imprimindo
a Hora
Me.lblStatusCache.Text
= System.DateTime.Now.ToString
End Sub
End Class
|
Após adicionar o código da Listagem 8, abra o UserControl no
modo <html> e adicione a linha :
<%@OutputCache Duration="60" VaryByParam="none"%>
Esse parametro no <html> do controle determina que ele
vai ser armazenado no Cache com uma duração de 60 segundos.
Agora arraste esse controle para a pagina (paginadeteste5.aspx) e
monte o layout conforme a Figura 17. Depois modifique o código
conforme a Listagem 9. |
Figura 17 - Layout de paginadeteste5.aspx
|
Listagem
9 - Exibindo Data/Hora em um Label dentro da pagina (paginadeteste5.aspx.vb)
Public Class
paginadeteste5
Inherits
System.Web.UI.Page
Private Sub
Page_Load(ByVal sender As
System.Object, _
ByVal e As
System.EventArgs) Handles MyBase.Load
Me.lblStatusHoraAtual.Text
= System.DateTime.Now.ToString
End
Sub
End Class |
Acesse a paginadeteste5.aspx e fique pressionando recarregar (F5) no
browser para ir atualizando a pagina, você vai observar
conforme Figura 18 que a hora do controle só atualiza a cada
60 segundos. Esse é o exemplo mais simples de se implementar, todavia
é a forma mais clara de se visualizar o funcionamento do Cache.
Existe muitos outros parâmetros adicionais a ser utilizado em um User
Control dentro do Cache. Recomendo uma pesquisa mais aprofundada sobre
esse assunto.
Figura 18 - Demonstrando cache com User Control.
|
Conclusão
O
controle User Control veio para substituir de vez os velhos #Includes
trazendo um padrão novo de desenvolvimento e reutilização de
código tal como aderência ao ASP.NET como utilização dos recursos
de OOP , Cache, Compilação, código separado do Layout...
dentre outros. Você pode usa-los tanto para implementação visual
quanto para código.
A partir desse artigo estou apresentando um novo padrão de
artigos, espero que tenha gostado. Sua participação é fundamental.
Mande suas sugestões.
Você que é de Salvador/Bahia venha para o grupo de usuários http://www.mutex.com.br
|
|