Exemplo de Controle Web de Composição
Este exemplo mostra como criar um controle chamado Register que demonstra as principais etapas necessárias para implementar um controle de servidor ASP.NET composto.Um controle composto usa controles filho para criar uma interface do usuário e executar outras lógicas.Como um controle composto depende de controles filho para sua funcionalidade, é significativamente mais fácil desenvolver um controle composto que você mesmo implementar todas as funcionalidades do controle.
Nesse exemplo, o controle Register usa controles filho para criar uma interface de usuário para inserir informações do usuário a fim de registrar em um Web Site.A interface do usuário consiste em dois TextBox controles, uma para inserir o nome do usuário e outro para inserir endereço de email do usuário e um Button controle para enviar as informações. Register também associa RequiredFieldValidator controles com os dois TextBox controles para certificar-se de que o usuário insere um nome e endereço de email. O evento Click do controle Button é gerado como o evento Submit do controle Register.
O controle Register depende dos recursos internos de controles filho para o seu comportamento.Por exemplo, Register depende dos controles TextBox para manipular dados de postagem, o controle Button para o evento de postagem e os controles RequiredFieldValidator para validação.
O código para o controle Register é descrito na seção "Discussão do Código" posteriormente neste tópico.Quando você examinar o código para o controle Register, você observará que a maior parte do código relaciona-se à criação e ao gerenciamento dos controles filho.
Listagem de Código para o Controle Register
' Register.vb
Option Strict On
Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace Samples.AspNet.VB.Controls
< _
AspNetHostingPermission(SecurityAction.Demand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
DefaultEvent("Submit"), _
DefaultProperty("ButtonText"), _
ToolboxData("<{0}:Register runat=""server""> </{0}:Register>") _
> _
Public Class Register
Inherits CompositeControl
Private submitButton As Button
Private nameTextBox As TextBox
Private nameLabel As Label
Private emailTextBox As TextBox
Private emailLabel As Label
Private emailValidator As RequiredFieldValidator
Private nameValidator As RequiredFieldValidator
Private Shared ReadOnly EventSubmitKey As New Object()
' The following properties are delegated to child controls.
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The text to display on the button.") _
> _
Public Property ButtonText() As String
Get
EnsureChildControls()
Return submitButton.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
submitButton.Text = value
End Set
End Property
< _
Bindable(True), _
Category("Default"), _
DefaultValue(""), _
Description("The user name.") _
> _
Public Property Name() As String
Get
EnsureChildControls()
Return nameTextBox.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
nameTextBox.Text = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("Error message for the name validator.") _
> _
Public Property NameErrorMessage() As String
Get
EnsureChildControls()
Return nameValidator.ErrorMessage
End Get
Set(ByVal value As String)
EnsureChildControls()
nameValidator.ErrorMessage = value
nameValidator.ToolTip = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The text for the name label.") _
> _
Public Property NameLabelText() As String
Get
EnsureChildControls()
Return nameLabel.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
nameLabel.Text = value
End Set
End Property
< _
Bindable(True), _
Category("Default"), _
DefaultValue(""), _
Description("The e-mail address.") _
> _
Public Property Email() As String
Get
EnsureChildControls()
Return emailTextBox.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
emailTextBox.Text = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("Error message for the e-mail validator.") _
> _
Public Property EmailErrorMessage() As String
Get
EnsureChildControls()
Return emailValidator.ErrorMessage
End Get
Set(ByVal value As String)
EnsureChildControls()
emailValidator.ErrorMessage = value
emailValidator.ToolTip = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The text for the e-mail label.") _
> _
Public Property EmailLabelText() As String
Get
EnsureChildControls()
Return emailLabel.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
emailLabel.Text = value
End Set
End Property
' The Submit event.
< _
Category("Action"), _
Description("Raised when the user clicks the button.") _
> _
Public Custom Event Submit As EventHandler
AddHandler(ByVal value As EventHandler)
Events.AddHandler(EventSubmitKey, value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
Events.RemoveHandler(EventSubmitKey, value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, _
ByVal e As System.EventArgs)
CType(Events(EventSubmitKey), _
EventHandler).Invoke(sender, e)
End RaiseEvent
End Event
' The method that raises the Submit event.
Protected Overridable Sub OnSubmit(ByVal e As EventArgs)
Dim submitHandler As EventHandler = _
CType(Events(EventSubmitKey), EventHandler)
If submitHandler IsNot Nothing Then
submitHandler(Me, e)
End If
End Sub
' Handles the Click event of the Button and raises
' the Submit event.
Private Sub submitButton_Click(ByVal source As Object, _
ByVal e As EventArgs)
OnSubmit(EventArgs.Empty)
End Sub
Protected Overrides Sub CreateChildControls()
Controls.Clear()
nameLabel = New Label()
nameTextBox = New TextBox()
nameTextBox.ID = "nameTextBox"
nameValidator = New RequiredFieldValidator()
nameValidator.ID = "validator1"
nameValidator.ControlToValidate = nameTextBox.ID
nameValidator.Text = "Failed validation."
nameValidator.Display = ValidatorDisplay.Static
emailLabel = New Label()
emailTextBox = New TextBox()
emailTextBox.ID = "emailTextBox"
emailValidator = New RequiredFieldValidator()
emailValidator.ID = "validator2"
emailValidator.ControlToValidate = emailTextBox.ID
emailValidator.Text = "Failed validation."
emailValidator.Display = ValidatorDisplay.Static
submitButton = New Button()
submitButton.ID = "button1"
AddHandler submitButton.Click, _
AddressOf submitButton_Click
Me.Controls.Add(nameLabel)
Me.Controls.Add(nameTextBox)
Me.Controls.Add(nameValidator)
Me.Controls.Add(emailLabel)
Me.Controls.Add(emailTextBox)
Me.Controls.Add(emailValidator)
Me.Controls.Add(submitButton)
End Sub
Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
AddAttributesToRender(writer)
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, _
"1", False)
writer.RenderBeginTag(HtmlTextWriterTag.Table)
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
nameLabel.RenderControl(writer)
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Td)
nameTextBox.RenderControl(writer)
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Td)
nameValidator.RenderControl(writer)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
emailLabel.RenderControl(writer)
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Td)
emailTextBox.RenderControl(writer)
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Td)
emailValidator.RenderControl(writer)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, _
"2", False)
writer.AddAttribute(HtmlTextWriterAttribute.Align, _
"right", False)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
submitButton.RenderControl(writer)
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.Write(" ")
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderEndTag()
End Sub
Protected Overrides Sub RecreateChildControls()
EnsureChildControls()
End Sub
End Class
End Namespace
// Register.cs
using System;
using System.ComponentModel;
using System.Drawing;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Samples.AspNet.CS.Controls
{
[
AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level=AspNetHostingPermissionLevel.Minimal),
DefaultEvent("Submit"),
DefaultProperty("ButtonText"),
ToolboxData("<{0}:Register runat=\"server\"> </{0}:Register>"),
]
public class Register : CompositeControl
{
private Button submitButton;
private TextBox nameTextBox;
private Label nameLabel;
private TextBox emailTextBox;
private Label emailLabel;
private RequiredFieldValidator emailValidator;
private RequiredFieldValidator nameValidator;
private static readonly object EventSubmitKey =
new object();
// The following properties are delegated to
// child controls.
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text to display on the button.")
]
public string ButtonText
{
get
{
EnsureChildControls();
return submitButton.Text;
}
set
{
EnsureChildControls();
submitButton.Text = value;
}
}
[
Bindable(true),
Category("Default"),
DefaultValue(""),
Description("The user name.")
]
public string Name
{
get
{
EnsureChildControls();
return nameTextBox.Text;
}
set
{
EnsureChildControls();
nameTextBox.Text = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description(
"Error message for the name validator.")
]
public string NameErrorMessage
{
get
{
EnsureChildControls();
return nameValidator.ErrorMessage;
}
set
{
EnsureChildControls();
nameValidator.ErrorMessage = value;
nameValidator.ToolTip = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text for the name label.")
]
public string NameLabelText
{
get
{
EnsureChildControls();
return nameLabel.Text;
}
set
{
EnsureChildControls();
nameLabel.Text = value;
}
}
[
Bindable(true),
Category("Default"),
DefaultValue(""),
Description("The e-mail address.")
]
public string Email
{
get
{
EnsureChildControls();
return emailTextBox.Text;
}
set
{
EnsureChildControls();
emailTextBox.Text = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description(
"Error message for the e-mail validator.")
]
public string EmailErrorMessage
{
get
{
EnsureChildControls();
return emailValidator.ErrorMessage;
}
set
{
EnsureChildControls();
emailValidator.ErrorMessage = value;
emailValidator.ToolTip = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text for the e-mail label.")
]
public string EmailLabelText
{
get
{
EnsureChildControls();
return emailLabel.Text;
}
set
{
EnsureChildControls();
emailLabel.Text = value;
}
}
// The Submit event.
[
Category("Action"),
Description("Raised when the user clicks the button.")
]
public event EventHandler Submit
{
add
{
Events.AddHandler(EventSubmitKey, value);
}
remove
{
Events.RemoveHandler(EventSubmitKey, value);
}
}
// The method that raises the Submit event.
protected virtual void OnSubmit(EventArgs e)
{
EventHandler SubmitHandler =
(EventHandler)Events[EventSubmitKey];
if (SubmitHandler != null)
{
SubmitHandler(this, e);
}
}
// Handles the Click event of the Button and raises
// the Submit event.
private void _button_Click(object source, EventArgs e)
{
OnSubmit(EventArgs.Empty);
}
protected override void RecreateChildControls()
{
EnsureChildControls();
}
protected override void CreateChildControls()
{
Controls.Clear();
nameLabel = new Label();
nameTextBox = new TextBox();
nameTextBox.ID = "nameTextBox";
nameValidator = new RequiredFieldValidator();
nameValidator.ID = "validator1";
nameValidator.ControlToValidate = nameTextBox.ID;
nameValidator.Text = "Failed validation.";
nameValidator.Display = ValidatorDisplay.Static;
emailLabel = new Label();
emailTextBox = new TextBox();
emailTextBox.ID = "emailTextBox";
emailValidator = new RequiredFieldValidator();
emailValidator.ID = "validator2";
emailValidator.ControlToValidate =
emailTextBox.ID;
emailValidator.Text = "Failed validation.";
emailValidator.Display = ValidatorDisplay.Static;
submitButton = new Button();
submitButton.ID = "button1";
submitButton.Click
+= new EventHandler(_button_Click);
this.Controls.Add(nameLabel);
this.Controls.Add(nameTextBox);
this.Controls.Add(nameValidator);
this.Controls.Add(emailLabel);
this.Controls.Add(emailTextBox);
this.Controls.Add(emailValidator);
this.Controls.Add(submitButton);
}
protected override void Render(HtmlTextWriter writer)
{
AddAttributesToRender(writer);
writer.AddAttribute(
HtmlTextWriterAttribute.Cellpadding,
"1", false);
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
nameLabel.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
nameTextBox.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
nameValidator.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
emailLabel.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
emailTextBox.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
emailValidator.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(
HtmlTextWriterAttribute.Colspan,
"2", false);
writer.AddAttribute(
HtmlTextWriterAttribute.Align,
"right", false);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
submitButton.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(" ");
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
}
}
Discussão de Código
O controle Register executa as seguintes tarefas que são comuns a todos os controles compostos:
Derivando da classe CompositeControl.
Criando controles filho, substituindo o método CreateChildControls.
A classe CompositeControl implementa a funcionalidade comum necessária por todos os controles compostos.Ela também possui um designer de controle associado que garante que controles filho sejam exibidos na superfície de design em um designer visual.
Observação: |
---|
A classe CompositeControl é nova no ASP.NET 2.0.Se você criou os controles personalizados no ASP.NET versão 1.0 ou 1.1, você precisou implementar a interface INamingContainer para criar um novo escopo de nomeação para controles filho.Além disso, você teve que substituir a propriedade Controls e chamar o método EnsureChildControls.No ASP.NET 2.0, essas e outras etapas são executadas pela classe CompositeControl. |
Você deve criar os controles filho no método CreateChildControls e não em OnInit ou outra fase do ciclo de vida.A arquitetura do controle de servidor se baseia em chamadas para CreateChildControls sempre que a coleção Controls for necessária, como durante a associação de dados (se aplicável).
O controle Register também ilustra como expor as propriedades de controles filho como propriedades de nível superior.Isso é útil quando você deseja permitir que o desenvolvedor de página acesse as propriedades de um controle filho.Por exemplo, Register expõe a propriedade Text do controle filho Button como sua própria propriedade ButtonText, conforme mostrado no código a seguir desenhado do exemplo:
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The text to display on the button.") _
> _
Public Property ButtonText() As String
Get
EnsureChildControls()
Return submitButton.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
submitButton.Text = value
End Set
End Property
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text to display on the button.")
]
public string ButtonText
{
get
{
EnsureChildControls();
return submitButton.Text;
}
set
{
EnsureChildControls();
submitButton.Text = value;
}
}
O controle Register não armazena ButtonText ou outras propriedades que ela delega a controles filho no estado de exibição porque os controles filho usam o estado de exibição para armazenar essas propriedades.Para obter informações sobre como gerenciar o estado das propriedades que não são delegadas a controles filho, consulte Exemplo das propriedades de controle do servidor.Esse tópico contém informações sobre como usar o dicionário ViewState para armazenar propriedades simples e implementar o gerenciamento de estado personalizado para as propriedades que possuem subpropriedades.
O controle Register mostra como gerar um evento a partir do manipulador do evento de um controle filho.O controle Register define um evento chamado Submit e gera o evento anexando um manipulador ao evento Click do controle filho Button.
Testar a Página para o Controle Register
O exemplo a seguir mostra uma página da Web ASP.NET que usa o controle Register.
<%@ Page Language="VB"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
Label1.Visible = False
End Sub
Sub Register_Submit(ByVal sender As Object, ByVal e As EventArgs)
' The application developer can implement
' logic here to enter registration data into
' a database or write a cookie
' on the user's computer.
' This example merely writes a message
' using the Label control on the page.
Label1.Text = String.Format( _
"Thank you, {0}! You are registered.", Register1.Name)
Label1.Visible = True
Register1.Visible = False
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" >
<title>
Register Control Test Page
</title>
</head>
<body>
<form id="form1" >
<aspSample:Register ButtonText="Submit"
OnSubmit="Register_Submit" ID="Register1"
Runat="server" NameLabelText="Name:" EmailLabelText="Email:"
EmailErrorMessage="You must enter your e-mail address."
NameErrorMessage="You must enter your name." />
<br />
<asp:Label ID="Label1" Runat="server" Text="Label">
</asp:Label>
<asp:ValidationSummary ID="ValidationSummary1"
Runat="server" DisplayMode="List" />
</form>
</body>
</html>
<%@ Page Language="C#"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
void Page_Load(object sender, EventArgs e)
{
Label1.Visible = false;
}
void Register_Submit(object sender, EventArgs e)
{
// The application developer can implement
// logic here to enter registration data into
// a database or write a cookie
// on the user's computer.
// This example merely writes a message
// using the Label control on the page.
Label1.Text = String.Format(
"Thank you, {0}! You are registered.",Register1.Name);
Label1.Visible = true;
Register1.Visible = false;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" >
<title>
Register Control Test Page
</title>
</head>
<body>
<form id="form1" >
<aspSample:Register ButtonText="Register"
OnSubmit="Register_Submit" ID="Register1"
Runat="server" NameLabelText="Name:"
EmailLabelText="Email:"
EmailErrorMessage="You must enter your e-mail address."
NameErrorMessage="You must enter your name." />
<br />
<asp:Label ID="Label1" Runat="server" Text="Label">
</asp:Label>
<asp:ValidationSummary ID="ValidationSummary1"
Runat="server" DisplayMode="List" />
</form>
</body>
</html>
Construindo e Usando o Exemplo
Para obter informações sobre a compilação e uso dos exemplos de controles personalizados, consulte Construindo os Exemplos de Controle de Servidor Personalizado.