Condividi tramite


Esempio di controllo Web composito

Aggiornamento: novembre 2007

Nell'esempio vengono illustrate le modalità di creazione di un controllo denominato Register che descrive i passaggi principali necessari per implementare un controllo server ASP.NET composito. Un controllo composito utilizza controlli figlio per creare un'interfaccia utente (UI) ed eseguire altra logica. Poiché la funzionalità di un controllo composito si basa su controlli figlio, è molto più semplice sviluppare un controllo composito anziché implementare la funzionalità di tutti i controlli.

In questo esempio, il controllo Register utilizza controlli figlio per creare un'interfaccia utente (UI) per l'immissione di informazioni utente per la registrazione in un sito Web. L'interfaccia utente è composta da due controlli TextBox, uno per l'immissione del nome utente e l'altro per l'indirizzo di posta elettronica, e un controllo Button per inviare le informazioni. Register associa inoltre i controlli RequiredFieldValidator ai due controlli TextBox per garantire che l'utente immetta un nome e un indirizzo di posta elettronica. L'evento Click del controllo Button viene generato come evento Submit del controllo Register.

Il comportamento del controllo Register è basato sulle funzionalità incorporate dei controlli figlio. Ad esempio, Register si basa sui controlli TextBox per gestire i dati di postback, il controllo Button per l'evento postback e i controlli RequiredFieldValidator per la convalida.

Il codice per il controllo Register è illustrato nella sezione "Illustrazione del codice", più avanti in questo argomento. Durante l'analisi del codice per il controllo Register, si noterà che la maggior parte del codice è correlata alla generazione e alla gestione di controlli figlio.

Listato di codice per il controllo 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("&nbsp")
            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("&nbsp;");
            writer.RenderEndTag();
            writer.RenderEndTag();

            writer.RenderEndTag();
        }
    }
}

Illustrazione del codice

Il controllo Register esegue le seguenti attività, comuni a tutti i controlli compositi:

La classe CompositeControl implementa la funzionalità comune richiesta da tutti i controlli compositi. Tale classe presenta inoltre una finestra di progettazione del controllo associata che garantisce che i controlli figlio vengano visualizzati nell'area di progettazione in una finestra di progettazione visiva.

Nota:

La classe CompositeControl rappresenta una novità di ASP.NET 2.0. Per creare controlli personalizzati in ASP.NET versione 1.0 o 1.1 era necessario implementare l'interfaccia INamingContainer per creare un nuovo ambito di denominazione per i controlli figlio. Inoltre, era necessario eseguire l'override della proprietà Controls e chiamare il metodo EnsureChildControls. In ASP.NET 2.0, questi e altri passaggi vengono svolti dalla classe CompositeControl.

È necessario creare i controlli figlio nel metodo CreateChildControls e non in OnInit o in qualsiasi altra fase del ciclo di vita. L'architettura del controllo server si basa su chiamate a CreateChildControls ogni volta che viene richiesto l'insieme Controls, come, ad esempio, durante l'associazione dei dati, se applicabile.

Il controllo Register illustra inoltre come esporre proprietà di controlli figlio come proprietà di primo livello. Questa operazione è utile quando si desidera consentire allo sviluppatore di pagine di accedere alle proprietà di un controllo figlio. Ad esempio, Register espone la proprietà Text del controllo figlio Button come proprietà propria ButtonText, come illustrato nel seguente codice dell'esempio:

< _
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;
    }
}

Il controllo Register non archivia ButtonText o altre proprietà che delega a controlli secondari nello stato di visualizzazione, poiché tali proprietà vengono archiviate dai controlli figlio mediante lo stato di visualizzazione. Per informazioni sulla gestione dello stato delle proprietà che non sono delegate a controlli figlio, vedere Esempio di proprietà dei controlli server. In quella sezione sono incluse informazioni sull'utilizzo del dizionario ViewState per l'archiviazione di proprietà semplici e l'implementazione della gestione personalizzata dello stato per proprietà che contengono sottoproprietà.

Il controllo Register illustra come generare un evento con il gestore eventi del controllo figlio. Il controllo Register definisce un evento denominato Submit e genera l'evento associando un gestore all'evento Click del controllo figlio Button.

Pagina di prova per il controllo Register

Nell'esempio seguente viene mostrata una pagina Web ASP.NET che utilizza il controllo 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>

Generazione e utilizzo dell'esempio

Per informazioni sulla compilazione e sull'utilizzo degli esempi del controllo personalizzato, vedere Generazione degli esempi dei controlli server personalizzati.

Vedere anche

Altre risorse

Sviluppo di controlli server ASP.NET personalizzati