Contrôle Web composite, exemple
Mise à jour : novembre 2007
Cet exemple montre comment créer un contrôle nommé Register, qui illustre les principales étapes requises pour implémenter un contrôle serveur ASP.NET composite. Un contrôle composite utilise des contrôles enfants pour créer une interface utilisateur et exécuter une autre logique. Puisqu'un contrôle composite s'appuie sur des contrôles enfants pour ses fonctionnalités, il est infiniment plus facile de développer un contrôle composite que d'implémenter soi-même toutes les fonctionnalités du contrôle.
Dans cet exemple, le contrôle Register utilise des contrôles enfants pour créer une interface utilisateur afin de saisir des informations utilisateur pour s'inscrire sur un site Web. L'interface utilisateur se compose de deux contrôles TextBox, l'un pour entrer le nom de l'utilisateur et l'autre pour entrer l'adresse de messagerie de l'utilisateur, ainsi qu'un contrôle Button pour envoyer les informations. Register associe également des contrôles RequiredFieldValidator aux deux contrôles TextBox pour être sûr que l'utilisateur entre un nom et une adresse de messagerie. L'événement Click du contrôle Button est déclenché en tant qu'événement Submit du contrôle Register.
Le contrôle Register s'appuie pour son comportement sur les fonctionnalités intégrées des contrôles enfants. Par exemple, Register s'appuie sur les contrôles TextBox pour gérer les données de publication, sur le contrôle Button pour l'événement de publication, et sur les contrôles RequiredFieldValidator pour la validation.
Le code du contrôle Register est décrit plus loin dans la section « Explication du code » de cette rubrique. Si vous examinez le code du contrôle Register, vous remarquerez que la majeure partie de ce code concerne la création et la gestion de contrôles enfants.
Liste du code du contrôle 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();
}
}
}
Explication du code
Le contrôle Register effectue les tâches suivantes, communes à tous les contrôles composites :
Dériver à partir de la classe CompositeControl.
Créer des contrôles enfants en substituant la méthode CreateChildControls.
La classe CompositeControl implémente les fonctionnalités communes nécessaires à tous les contrôles composites. Elle dispose également d'un concepteur de contrôles associé qui veille à ce que les contrôles enfants soient affichés sur l'aire de conception d'un concepteur visuel.
Remarque : |
---|
La classe CompositeControl est une nouveauté d'ASP.NET 2.0. Si vous avez déjà créé des contrôles personnalisés dans la version 1.0 ou 1.1 d'ASP.NET, vous vous rappelez qu'il fallait implémenter l'interface INamingContainer pour créer une nouvelle portée de désignation pour les contrôles enfants. De plus, vous deviez substituer la propriété Controls et appeler la méthode EnsureChildControls. Dans ASP.NET 2.0, ces étapes, ainsi que d'autres, sont effectuées par la classe CompositeControl. |
Vous devez créer les contrôles enfants dans la méthode CreateChildControls et non dans OnInit ou dans une autre phase de cycle de vie. L'architecture de contrôle serveur s'appuie sur les appels à CreateChildControls chaque fois que la collection Controls est nécessaire, par exemple au moment d'une liaison de données (le cas échéant).
Le contrôle Register montre également comment exposer des propriétés de contrôles enfants en tant que propriétés de niveau supérieur. Cela est utile lorsque vous souhaitez permettre au développeur de pages d'accéder aux propriétés d'un contrôle enfant. Par exemple, Register expose la propriété Text du contrôle enfant Button comme étant sa propre propriété ButtonText, ainsi que le montre le code suivant tiré de l'exemple :
< _
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;
}
}
Le contrôle Register ne stocke pas ButtonText dans l'état d'affichage, ni d'autres propriétés qu'il délègue aux contrôles enfants, parce que les contrôles enfants utilisent l'état d'affichage pour stocker ces propriétés. Pour plus d'informations sur la gestion de l'état des propriétés non déléguées aux contrôles enfants, consultez Propriétés de contrôle serveur, exemple. Cette rubrique contient des informations sur l'utilisation du dictionnaire ViewState pour stocker des propriétés simples et implémenter une gestion d'état personnalisée pour les propriétés possédant des sous-propriétés.
Le contrôle Register montre comment déclencher un événement depuis le gestionnaire d'événement d'un contrôle enfant. Le contrôle Register définit un événement nommé Submit et le déclenche en attachant un gestionnaire à l'événement Click du contrôle enfant Button.
Page de test du contrôle Register
L'exemple suivant montre une page Web ASP.NET qui utilise le contrôle 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>
Génération et utilisation de l'exemple
Pour plus d'informations sur la compilation et l'utilisation des exemples de contrôles personnalisés, consultez Exemples de création de contrôles serveur personnalisés.