次の方法で共有


テンプレート サーバー コントロールの例

更新 : 2007 年 11 月

この例では、VacationHome というコントロールを使用してテンプレート サーバー コントロールを実装する方法を示します。VacationHome コントロールは、Title プロパティと Caption プロパティという 2 つの公開するプロパティを定義します。ページ デザイナはデザイン時にこれらプロパティの値を設定します。コントロールではそのプロパティ値を実行時に使用し、子コントロールのプロパティを設定します。コントロールの <Template> 要素を編集することによって、コントロールのユーザー インターフェイスを定義するコントロールとマークアップを指定できます。また、このコントロールによって、<#% Container %> 構文を使用できるようになるため、デザイン時にテンプレートのマークアップで Title 値と Caption 値を参照し、レンダリングされる出力に表示することができます。ページ デザイナは、次のような ASP.NET Web ページを作成できます。

<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" 
      runat="server" 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>

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

}

コードの説明

テンプレート コントロールは、ITemplate 型のプロパティを追加し、コントロールの名前付けコンテナを定義することによって、CompositeControl を拡張できます。名前付けコンテナを定義すると、<#%Container%> の構文を使用してテンプレートを定義できるようになります。テンプレート コントロールは、テンプレートで定義されるコントロールをホストするために、Control から派生する型のプロパティも定義します。テンプレートのプロパティ、ホストのコントロール、および名前付けコンテナの動作を調整するために、特定の属性とメンバのオーバーライドが実装されます。

VacationHome のようなテンプレート コントロールの主な実装の要件を次の一覧にまとめます。各要件の詳細については、一覧の後で説明します。VacationHome コントロールの特徴は次のとおりです。

  • CompositeControl 基本クラスから派生します。テンプレート コントロールは、特別な種類の複合コントロールです。テンプレート コントロールは WebControl から派生させることもできますが、CompositeControl には、<#%Container%> の構文を使用するための INamingContainer の実装が追加されています。

  • ITemplate 型のプロパティを実装し、関連するメタデータの属性を適用して、永続性と名前付けコンテナを定義します。

  • テンプレート要素で定義されるコントロールをホストするために、Control 型のプロパティまたは Control から派生するクラスを公開します。このコントロールはテンプレート コンテナと呼ばれます。

  • CreateChildControls メソッドをオーバーライドして、テンプレート コンテナの Controls コレクションのテンプレート コントロールをインスタンス化します。

  • ページの開発者がテンプレートを指定しない場合にコントロールが使用する既定のテンプレートを定義します (省略可能)。

  • コントロールのデザイナ クラスを定義します (省略可能)。デザイナ クラスによって、テンプレートをビジュアル デザイナで編集できるようになります。

ITemplate プロパティに適用される属性は、BrowsableAttributePersistenceModeAttribute、および TemplateContainerAttribute の各属性です。TemplateContainerAttribute は、テンプレートの <#%Container.Title%> などの式の Container 変数を解決する際にページ パーサーが使用するコントロールの型を指定します。指定する型には INamingContainer を実装し、コントロールのデータのプロパティを定義する必要があります (この場合は Caption と Title)。この型は、テンプレートの所有者の型またはコントロール ツリーの上位のコントロールにすることもできます。VacationHome コントロールでは、TemplateContainerAttribute コンストラクタに型が渡されるコントロールはテンプレートの所有者ではなく、VacationHome コントロール自身です。テンプレートは通常、ビジュアル デザイナのプロパティ編集ウィンドウでは編集しないため、BrowsableAttribute は false に設定されます。テンプレートの仕様はコントロールの内部要素として記述されるため、PersistenceModeAttributeInnerProperty に設定されます。

テンプレート コントロールは、テンプレートが作成するコントロールのコンテナになる Control 型のプロパティを定義する必要があります。この例の VacationHome コントロールは WebControl から派生する TemplateOwner 型の Owner プロパティを定義します。TemplateOwner クラスはビジュアル デザイナでツールボックスのサポートを必要としないため、TemplateOwner クラスには ToolboxItem(false) のマークが付けられます。詳細については、「ToolboxItemAttribute」を参照してください。テンプレートのコントロールはインスタンス化されて Owner コントロールの Controls プロパティに追加されます。コントロールが複数の ITemplate プロパティを公開する場合は、各テンプレートに対して個別のテンプレート コンテナのプロパティを定義することもできます。Owner プロパティはパブリック プロパティとして公開されます。これによって、ページ デザイナは FindControl メソッドを使用して実行時にテンプレートの特定のコントロールを参照できます。

VacationHome コントロールは、CreateChildControls 基本メソッドをオーバーライドします。CreateChildControls メソッドは、Template プロパティによって指定されるコントロールをインスタンス化し、Owner オブジェクトの Controls コレクションに追加します。Owner オブジェクトは VacationHome インスタンスの Controls コレクションに追加され、コントロールがレンダリングできるようになります。

ページの開発者がテンプレートを定義していない場合、VacationHome は ITemplate から派生する DefaultTemplate のインスタンスを作成します。InstantiateIn メソッドは、Title プロパティと Caption プロパティを表示するための 2 つの Label コントロールを作成します。各コントロールの DataBinding イベントのためにイベント ハンドラ メソッドが作成されます。DataBinding イベント ハンドラは VacationHome の適切なプロパティ (Title または Caption) に Text プロパティを設定します。

VacationHome クラスのデザイナを実装する VacationHomeDesigner クラスは、ControlDesigner から派生します。初期化中に、TemplateEditing と共に呼び出される SetViewFlags メソッドによって、デザイン時にテンプレートを編集できます。GetDesignTimeHtml メソッドは、テンプレート編集モードではない場合にコントロールをレンダリングするようにオーバーライドされます。オーバーライドされた TemplateGroups プロパティのコードは、単一のテンプレートを含むテンプレート グループを 1 つ定義します。各 TemplateGroup オブジェクトは、ビジュアル デザイナのテンプレート編集ユーザー インターフェイスにテンプレート編集の選択肢を追加します。Visual Studio 2005 のテンプレート編集の選択肢は、コントロールに関連付けられるスマート タグに表示されます。VacationHome コントロールの編集の選択肢は "Item" のみです。各 TemplateDefinition オブジェクトは、デザイナで編集するためのテンプレートを作成します。TemplateDefinition コンストラクタの templatePropertyName パラメータには、コントロールのテンプレート プロパティの名前を指定します。DesignerAttribute は、デザイナ クラスを指定するために VacationHome クラスに適用されます。

VacationHome コントロールのテスト ページ

VacationHome コントロールを使用する .aspx ページの例を次に示します。ページのコントロールの最初のインスタンスは、コントロールの ITemplate プロパティのテンプレートを指定します。2 番目のインスタンスは ITemplate プロパティを指定しないため、VacationHome コントロールは実行時に既定のテンプレートを使用します。

<%@ Page Language="VB"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
    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" runat="server">
    <title>
      VacationHome Control Test Page
    </title>
  </head>
  <body>
    <form id="form1" runat="server">
    <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" runat="server" 
        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 runat="server">
  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" runat="server">
    <title>
      VacationHome Control Test Page
    </title>
  </head>
  <body>
    <form id="form1" runat="server">
    <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" runat="server" 
        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>

例のビルドと使用

コントロールをビルドしてページ内で使用する方法については、「カスタム サーバー コントロールの例のビルド」を参照してください。コンパイルには System.Design アセンブリへの参照を追加する必要があります。

参照

概念

複合 Web コントロールの例

子コントロールの型指定されたスタイルの例

その他の技術情報

ASP.NET カスタム サーバー コントロールの開発