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