次の方法で共有


複合 Web コントロールの例

更新 : 2007 年 11 月

この例では、複合 ASP.NET サーバー コントロールを実装するための主な手順を示す Register というコントロールを作成する方法を示します。複合コントロールは、子コントロールを使用してユーザー インターフェイス (UI) を作成し、他のロジックを実行します。複合コントロールは子コントロールを使用して機能を提供するため、コントロールのすべての機能を各自で実装するよりはるかに簡単になります。

この例の Register コントロールは、子コントロールを使用してユーザーが Web サイトの登録情報を入力するためのユーザー インターフェイス (UI) を作成します。このユーザー インターフェイスは、ユーザー名を入力するためのコントロールとユーザーの電子メール アドレスを入力するためのコントロールの 2 つの TextBox コントロール、および情報を送信するための Button コントロールで構成されます。Register は、ユーザーが名前と電子メール アドレスを入力したことを確認するために、この 2 つの TextBox コントロールに RequiredFieldValidator コントロールも関連付けます。Button コントロールの Click イベントは、Register コントロールの Submit イベントとして発生します。

Register コントロールの機能は、子コントロールの組み込み機能に依存します。たとえば、Register は TextBox コントロールによってポストバック データを処理し、Button コントロールによってポストバック イベントを処理し、RequiredFieldValidator コントロールによって検証します。

Register コントロールのコードについては、この後の「コードの説明」で説明します。Register コントロールのコードを確認すると、コードの大部分が子コントロールの作成と管理に関係していることがわかります。

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

コードの説明

Register コントロールは、すべての複合コントロールに共通する次のようなタスクを実行します。

CompositeControl クラスは、すべての複合コントロールが必要とする共通機能を実装します。このクラスには、子コントロールをビジュアル デザイナのデザイン サーフェイスに表示するためのコントロール デザイナも関連付けられています。

3257x3ea.alert_note(ja-jp,VS.90).gifメモ :

CompositeControl クラスは、ASP.NET 2.0 で新たに導入されました。ASP.NET バージョン 1.0 または 1.1 でカスタム コントロールを作成すると、INamingContainer インターフェイスを実装して子コントロールのための新しい名前付けスコープを作成する必要があります。さらに、Controls プロパティをオーバーライドし、EnsureChildControls メソッドを呼び出す必要もあります。ASP.NET 2.0 では、以上およびその他の手順は CompositeControl クラスが実行します。

子コントロールは、OnInit またはその他のライフサイクルの段階ではなく、CreateChildControls メソッドで作成する必要があります。サーバー コントロールのアーキテクチャは、データ連結などで Controls コレクションが必要になる場合に、必ず CreateChildControls の呼び出しに依存します。

Register コントロールは、子コントロールのプロパティをトップ レベルのプロパティとして公開する方法も示します。これは、ページの開発者が子コントロールのプロパティにアクセスできるようにする場合に便利です。たとえば、例から引用されている次のコードにあるように、Register は Button 子コントロールの Text プロパティを自身の ButtonText プロパティとして公開します。

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

Register コントロールはビューステートの子コントロールに代行させる ButtonText またはその他のプロパティを格納しません。これは、子コントロールがこれらのプロパティを格納するためにビューステートを使用するためです。子コントロールに代行させないプロパティの状態管理の方法については、「サーバー コントロールのプロパティの例」を参照してください。このトピックには、ViewState 辞書を使用して単純なプロパティを格納し、サブプロパティを含むプロパティのカスタム状態管理を実装することに関する情報が記載されています。

Register コントロールは、子コントロールのイベント ハンドラからイベントを発生させる方法を示します。Register コントロールは Submit というイベントを定義し、Button 子コントロールの Click イベントにハンドラを追加してこのイベントを発生します。

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

Register コントロールを使用する ASP.NET Web ページの例を次に示します。

<%@ 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)
        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" runat="server">
    <title>
      Register Control Test Page
    </title>
  </head>
  <body>
    <form id="form1" runat="server">
      <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 runat="server">
  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" runat="server">
    <title>
      Register Control Test Page
    </title>
  </head>
  <body>
    <form id="form1" runat="server">
      <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>

例のビルドと使用

カスタム コントロールの例のコンパイルと使用については、「カスタム サーバー コントロールの例のビルド」を参照してください。

参照

その他の技術情報

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