Compartilhar via


Exemplo de Modelo de Controle de Servidor

Este exemplo mostra um controle chamado VacationHome que demonstra como implementar um modelo de controle de servidor.O controle VacationHome define duas propriedades expostas, Title e Caption.O criador da página define os valores dessas propriedades em tempo de design e o controle usa esses valores de propriedade em tempo de execução para definir propriedades para seus controles filho.Editando o elemento <Template> do controle, o desenvolvedor de página especifica os controles e marcações que definem a interface do usuário do controle.The control also enables page developers to use the <#% Container %> syntax, so that Title and Caption values can be referred to in the template markup at design time and displayed in the rendered output.Um criador da página pôde criar uma página da Web ASP.NET com esta aparência:

<aspSample:VacationHome ID="VacationHome1" 
  Title="Condo for Rent in Hawaii"  
  Caption="Ocean view starting from $200" 
  Runat="server" Width="230px" Height="129px">
  <Template>
    <table bgcolor="aqua" align="center" id="Table1" 
       style="width: 286px; height: 260px">
      <tr>
        <td style="width: 404px" align="center">
          <asp:Label ID="Label1" Runat="server"
            Text="<%#Container.Title%>" 
             Font-Names="Arial, Helvetica"></asp:Label>
        </td>
      </tr>
      <tr>
        <td style="width: 404px">
        <asp:Image ID="Image1" Runat="server" 
          ImageUrl="~/images/hawaii.jpg" />
        </td>
      </tr>
      <tr>
        <td style="width: 404px; height: 26px;" align="center">
          <asp:Label ID="Label2" Runat="server" 
            Text="<%#Container.Caption%>" 
            Font-Names="Arial, Helvetica">
          </asp:Label>
        </td>
      </tr>
    </table>
  </Template>
</aspSample:VacationHome>

Listagem de Código para o Controle VacationHome

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
Imports System.Web.UI.Design

Namespace Samples.AspNet.VB.Controls
    < _
    AspNetHostingPermission(SecurityAction.Demand, _
        Level:=AspNetHostingPermissionLevel.Minimal), _
    AspNetHostingPermission(SecurityAction.InheritanceDemand, _
        Level:=AspNetHostingPermissionLevel.Minimal), _
    Designer(GetType(VacationHomeDesigner)), _
    DefaultProperty("Title"), _
    ToolboxData( _
        "<{0}:VacationHome runat=""server""> </{0}:VacationHome>") _
    > _
    Public Class VacationHome
        Inherits CompositeControl
        Private _template As ITemplate
        Private _owner As TemplateOwner

        < _
        Bindable(True), _
        Category("Data"), _
        DefaultValue(""), _
        Description("Caption") _
        > _
        Public Overridable Property Caption() As String
            Get
                Dim s As String = CStr(ViewState("Caption"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("Caption") = value
            End Set
        End Property

        < _
        Browsable(False), _
        DesignerSerializationVisibility( _
            DesignerSerializationVisibility.Hidden) _
        > _
        Public ReadOnly Property Owner() As TemplateOwner
            Get
                Return _owner
            End Get
        End Property

        < _
        Browsable(False), _
        PersistenceMode(PersistenceMode.InnerProperty), _
    DefaultValue(GetType(ITemplate), ""), _
    Description("Control template"), _
        TemplateContainer(GetType(VacationHome)) _
        > _
        Public Overridable Property Template() As ITemplate
            Get
                Return _template
            End Get
            Set(ByVal value As ITemplate)
                _template = value
            End Set
        End Property

        < _
        Bindable(True), _
        Category("Data"), _
        DefaultValue(""), _
        Description("Title"), _
        Localizable(True) _
        > _
        Public Property Title() As String
            Get
                Dim s As String = CStr(ViewState("Title"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("Title") = value
            End Set
        End Property


        Protected Overrides Sub CreateChildControls()
            Controls.Clear()
            _owner = New TemplateOwner()

            Dim temp As ITemplate = _template
            If temp Is Nothing Then
                temp = New DefaultTemplate
            End If

            temp.InstantiateIn(_owner)
            Me.Controls.Add(_owner)
        End Sub

        Public Overrides Sub DataBind()
            CreateChildControls()
            ChildControlsCreated = True
            MyBase.DataBind()
        End Sub


    End Class

    <ToolboxItem(False)> _
    Public Class TemplateOwner
        Inherits WebControl
    End Class

#Region "DefaultTemplate"
    NotInheritable Class DefaultTemplate
        Implements ITemplate

        Sub InstantiateIn(ByVal owner As Control) _
            Implements ITemplate.InstantiateIn
            Dim title As New Label
            AddHandler title.DataBinding, AddressOf title_DataBinding
            Dim linebreak As New LiteralControl("<br/>")
            Dim caption As New Label
            AddHandler caption.DataBinding, _
                AddressOf caption_DataBinding
            owner.Controls.Add(title)
            owner.Controls.Add(linebreak)
            owner.Controls.Add(caption)
        End Sub

        Sub caption_DataBinding(ByVal sender As Object, _
            ByVal e As EventArgs)
            Dim source As Label = CType(sender, Label)
            Dim container As VacationHome = _
                CType(source.NamingContainer, VacationHome)
            source.Text = container.Caption
        End Sub


        Sub title_DataBinding(ByVal sender As Object, _
            ByVal e As EventArgs)
            Dim source As Label = CType(sender, Label)
            Dim container As VacationHome = _
                CType(source.NamingContainer, VacationHome)
            source.Text = container.Caption
        End Sub
    End Class
#End Region


    Public Class VacationHomeDesigner
        Inherits ControlDesigner

        Public Overrides Sub Initialize(ByVal Component As IComponent)
            MyBase.Initialize(Component)
            SetViewFlags(ViewFlags.TemplateEditing, True)
        End Sub

        Public Overloads Overrides Function GetDesignTimeHtml() As String
            Return "<span>This is design-time HTML</span>"
        End Function

        Public Overrides ReadOnly Property TemplateGroups() As TemplateGroupCollection
            Get
                Dim collection As New TemplateGroupCollection
                Dim group As TemplateGroup
                Dim template As TemplateDefinition
                Dim control As VacationHome

                control = CType(Component, VacationHome)
                group = New TemplateGroup("Item")
                template = New TemplateDefinition(Me, "Template", control, "Template", True)
                group.AddTemplateDefinition(template)
                collection.Add(group)
                Return collection
            End Get
        End Property
    End Class

End Namespace
// VacationHome.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;
using System.Web.UI.Design;

namespace Samples.AspNet.CS.Controls
{
    [
    AspNetHostingPermission(SecurityAction.InheritanceDemand, 
        Level=AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
    Designer(typeof(VacationHomeDesigner)),
    DefaultProperty("Title"),
    ToolboxData(
        "<{0}:VacationHome runat=\"server\"> </{0}:VacationHome>"),
    ]
    public class VacationHome : CompositeControl
    {
        private ITemplate templateValue;
        private TemplateOwner ownerValue;

        [
        Bindable(true),
        Category("Data"),
        DefaultValue(""),
        Description("Caption")
        ]
        public virtual string Caption
        {
            get
            {
                string s = (string)ViewState["Caption"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["Caption"] = value;
            }
        }

        [
        Browsable(false),
        DesignerSerializationVisibility(
            DesignerSerializationVisibility.Hidden)
        ]
        public TemplateOwner Owner
        {
            get
            {
                return ownerValue;
            }
        }

        [
        Browsable(false),
        PersistenceMode(PersistenceMode.InnerProperty),
        DefaultValue(typeof(ITemplate), ""),
        Description("Control template"),
        TemplateContainer(typeof(VacationHome))
        ]
        public virtual ITemplate Template
        {
            get
            {
                return templateValue;
            }
            set
            {
                templateValue = value;
            }
        }

        [
        Bindable(true),
        Category("Data"),
        DefaultValue(""),
        Description("Title"),
        Localizable(true)
        ]
        public virtual string Title
        {
            get
            {
                string s = (string)ViewState["Title"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["Title"] = value;
            }
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();
            ownerValue = new TemplateOwner();

            ITemplate temp = templateValue;
            if (temp == null)
            {
                temp = new DefaultTemplate();
            }

            temp.InstantiateIn(ownerValue);
            this.Controls.Add(ownerValue);
        }

        public override void DataBind()
        {
            CreateChildControls();
            ChildControlsCreated = true;
            base.DataBind();
        }

    }

    [
    ToolboxItem(false)
    ]
    public class TemplateOwner : WebControl
    {
    }

    #region DefaultTemplate
    sealed class DefaultTemplate : ITemplate
    {
        void ITemplate.InstantiateIn(Control owner)
        {
            Label title = new Label();
            title.DataBinding += new EventHandler(title_DataBinding);

            LiteralControl linebreak = new LiteralControl("<br/>");

            Label caption = new Label();
            caption.DataBinding 
                += new EventHandler(caption_DataBinding);

            owner.Controls.Add(title);
            owner.Controls.Add(linebreak);
            owner.Controls.Add(caption);

        }

        void caption_DataBinding(object sender, EventArgs e)
        {
            Label source = (Label)sender;
            VacationHome container = 
                (VacationHome)(source.NamingContainer);
            source.Text = container.Caption;
        }

        void title_DataBinding(object sender, EventArgs e)
        {
            Label source = (Label)sender;
            VacationHome container = 
                (VacationHome)(source.NamingContainer);
            source.Text = container.Title;
        }
    }
    #endregion


   public class VacationHomeDesigner : ControlDesigner
   {

        public override void Initialize(IComponent Component)
        {
            base.Initialize(Component);
            SetViewFlags(ViewFlags.TemplateEditing, true);
        }

        public override string GetDesignTimeHtml()
        {
            return "<span>This is design-time HTML</span>";
        }

        public override TemplateGroupCollection TemplateGroups
        {
            get {
                TemplateGroupCollection collection = new TemplateGroupCollection();
                TemplateGroup group;
                TemplateDefinition template;
                VacationHome control;

                control = (VacationHome)Component;
                group = new TemplateGroup("Item");
                template = new TemplateDefinition(this, "Template", control, "Template", true);
                group.AddTemplateDefinition(template);
                collection.Add(group);
                return collection;
            }
        }
    }

}

Discussão de Código

Um controle modelo estende o CompositeControl, adicionando uma propriedade do tipo ITemplate e definindo o contêiner de nomeação para o controle.Definindo um contêiner de nomeação, você permite que o desenvolvedor de página use a sintaxe <#%Container%> na definição de modelo.O modelo controle também define uma propriedade de um tipo que é derivado de Control para hospedar os controles definidos no modelo.Atributos específicos e substituição de membros são implementadas para coordenar a propriedade do modelo, controle host e comportamento do contêiner de nomeação.

A lista a seguir resume os requisitos principais de implementação para um controle modelo conforme demonstrado por VacationHome.Detalhes sobre cada requisito são fornecidos na discussão sobre a lista a seguir.O controle VacationHome demonstra:

  • A derivação a partir da classe base CompositeControl.Um controle modelo é um tipo especial de controle composto.Você também pode derivar de WebControl, mas CompositeControl adiciona a implementação para INamingContainer, que permite o uso da sintaxe <#%Container%>.

  • Implemente uma propriedade do tipo ITemplate e aplique atributos metadados relevantes a ele para definir sua persistência e o contêiner de nomeação.

  • Expor uma propriedade do tipo Control ou uma classe derivada de Control que serve para hospedar os controles definidoa no elemento de modelo.Esse controle é conhecido como o recipiente de modelo.

  • Substituia o método CreateChildControls para instanciar os controles de modelo na coleção Controls do recipiente de modelo.

  • Opcionalmente, defina um modelo padrão, que usa o controle quando o desenvolvedor de página não especifica um modelo.

  • Opcionalmente, defina uma classe do designer para o controle.A classe do designer permite ao desenvolvedor de página editar os modelos em um designer visual.

Os atributos aplicados à propriedade ITemplate são BrowsableAttribute, PersistenceModeAttribute e TemplateContainerAttribute.O TemplateContainerAttribute especifica o tipo do controle que o analisador de página deve usar ao resolver a variável Container em uma expressão como <#%Container.Title%> em um modelo.O tipo especificado deve implementar INamingContainer e definir as propriedades de dados (neste caso Caption e Title) para o controle.Esse tipo pode ser o tipo do proprietário do modelo ou de um controle mais para cima na árvore de controle.No controle VacationHome, o controle cujo tipo é passado para o construtor TemplateContainerAttribute não é o modelo proprietário, mas o controle VacationHome propriamente dito.O BrowsableAttribute é definida como false, porque os modelos são normalmente não editados na janela de edição de propriedade em um designer do Visual.O PersistenceModeAttribute é definido como InnerProperty, porque a especificação de modelo é gravada como um elemento interno do controle.

O controle modelo deve definir uma propriedade do tipo Control que se torna o recipiente para os controles criados pelo modelo.No exemplo, o controle VacationHome define a propriedade Owner, que é do tipo TemplateOwner, que por sua vez é derivada de WebControl.A classe TemplateOwner é marcada com ToolboxItem(false) para indicar que a classe TemplateOwner não precisa da Caixa de Ferramentas de suporte em um designer visual.Para obter mais informações, consulte ToolboxItemAttribute.Controles no modelo são instanciados e são adicionados para a propriedade Controls do controle Owner.Se o controle expõe várias propriedades ITemplate, você pode definir uma propriedade de recipiente modelo separado para cada modelo.A propriedade Owner é exposta como uma propriedade pública.Isso permite ao criador da página usar o método FindControl para fazer referência a controles específicos no modelo em tempo de execução.

O controle VacationHome substitui o método base CreateChildControls.O método CreateChildControls instancia os controles especificados na propriedade Template e os adiciona à coleção Controls do objeto Owner .O objeto Owner em seguida é adicionado à coleção Controls da instância VacationHome , e o controle, em seguida, pode ser processado.

Se o desenvolvedor de página não tiver definido um modelo, em seguida, o VacationHome cria uma instância do DefaultTemplate, que é derivado de ITemplate.O método InstantiateIn cria dois controles Label para exibir as propriedades Title e Caption.E o método de manipulador de eventos é criado para o evento DataBinding de cada controle.O manipulador de evento DataBinding define a propriedade Text como a propriedade apropriada (Title ou Caption) de VacationHome.

A classe VacationHomeDesigner que implementa um designer para a classe VacationHome deriva de ControlDesigner.Durante a inicialização, o método SetViewFlags, chamado com TemplateEditing, permite a edição em tempo de design do modelo.O método GetDesignTimeHtml é substituído ao processar o controle quando ele não estiver em modo de edição de modelo.O código na propriedade TemplateGroups sobrescrita define um grupo de modelos que contém um modelo.Cada objeto TemplateGroup adiciona um modelo Editando Escolha na interface do usuário no designer do edito de modelos visual.(No 2005 Visual Studio, opções do modelo-edição são exibidas em uma marca inteligente associada ao controle.) No controle VacationHome, a opção de edição somente é "item".Cada objeto TemplateDefinition cria um modelo para edição no designer.O parâmetro templatePropertyName do construtor TemplateDefinition especifica o nome da propriedade de modelo no controle.O DesignerAttribute é aplicado à classe VacationHome para especificar a classe do designer.

Testar Página para o Controle VacationHome

The following example shows an .aspx page that uses the VacationHome control.A primeira instância do controle na página especifica um modelo para a propriedade ITemplate do controle.A segunda instância não especifica a propriedade ITemplate, que faz com que o controle VacationHome use o modelo padrão no tempo de execução.

<%@ 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)
        If Not IsPostBack Then
            VacationHome1.DataBind()
            VacationHome2.DataBind()
        End If
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head id="Head1" >
    <title>
      VacationHome Control Test Page
    </title>
  </head>
  <body>
    <form id="form1" >
    <aspSample:VacationHome ID="VacationHome1" 
      Title="Condo for Rent in Hawaii"  
      Caption="Ocean view starting $200" 
      Runat="server" Width="230px" Height="129px">
    <Template>
      <table id="TABLE1"  
        style="width: 286px; height: 260px; 
        background-color:Aqua; text-align:center">
         <tr>
          <td style="width: 404px" align="center">
            <asp:Label ID="Label1" Runat="server" 
              Text="<%#Container.Title%>" 
              Font-Names="Arial, Helvetica"></asp:Label>
          </td>
        </tr>
        <tr>
          <td style="width: 404px">
            <asp:Image ID="Image1" Runat="server" 
              ImageUrl="~/images/hawaii.jpg" 
              AlternateText="Hawaii home" />
          </td>
        </tr>
        <tr>
          <td style="width: 404px; height: 26px;" align="center">
            <asp:Label ID="Label2" Runat="server" 
              Text="<%#Container.Caption%>" 
              Font-Names="Arial, Helvetica">
            </asp:Label>
          </td>
        </tr>
      </table>
     </Template>
    </aspSample:VacationHome>  
    <br /> <br />
      <br />
    The VacationHome control rendered with its default template:
    <br /> <br />
    <aspSample:VacationHome ID="VacationHome2" 
      Title="Condo for Rent in Hawaii" 
      Caption="Ocean view starting $200" 
      Runat="server" BorderStyle="Solid" BackColor="#66ffff" 
      Height="30px" Width="238px" Font-Names="Arial, Helvetica" />
    </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)
  {
    if (!IsPostBack)
    {
      VacationHome1.DataBind();
      VacationHome2.DataBind();
    }
  }

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head id="Head1" >
    <title>
      VacationHome Control Test Page
    </title>
  </head>
  <body>
    <form id="form1" >
    <aspSample:VacationHome ID="VacationHome1" 
      Title="Condo for Rent in Hawaii"  
      Caption="Ocean view starting $200" 
      Runat="server" Width="230px" Height="129px">
    <Template>
      <table id="TABLE1"  
        style="width: 286px; height: 260px; 
        background-color:Aqua; text-align:center">
        <tr>
          <td style="width: 404px" align="center">
            <asp:Label ID="Label1" Runat="server" 
              Text="<%#Container.Title%>" 
              Font-Names="Arial, Helvetica"></asp:Label>
          </td>
        </tr>
        <tr>
          <td style="width: 404px">
            <asp:Image ID="Image1" Runat="server" 
              ImageUrl="~/images/hawaii.jpg" 
              AlternateText="Hawaii home" />
          </td>
        </tr>
        <tr>
          <td style="width: 404px; height: 26px;" align="center">
            <asp:Label ID="Label2" Runat="server" 
              Text="<%#Container.Caption%>" 
              Font-Names="Arial, Helvetica">
            </asp:Label>
          </td>
        </tr>
      </table>
     </Template>
    </aspSample:VacationHome>  
    <br /> <br />
      <br />
    The VacationHome control rendered with its default template:
    <br /> <br />
    <aspSample:VacationHome ID="VacationHome2" 
      Title="Condo for Rent in Hawaii" 
      Caption="Ocean view starting $200" 
      Runat="server" BorderStyle="Solid" BackColor="#66ffff" 
      Height="30px" Width="238px" Font-Names="Arial, Helvetica" />
    </form>
  </body>
</html>

Construindo e Usando o Exemplo

Para mais informações a respeito da construção do controle e uso dele em uma página, consulte Construindo os Exemplos de Controle de Servidor Personalizado.Você deve adicionar uma referência ao conjunto de módulos (Assembly) System.Design para a compilação.

Consulte também

Conceitos

Exemplo de Controle Web de Composição

Exemplo de Estilos Tipados para Controles Filho

Outros recursos

Desenvolvendo Controles Personalizados ASP.NET Server