Пример составного веб-элемента управления

Visual Studio 2010

Обновлен: Ноябрь 2007

Этот пример показывает, как создать элемент управления с именем Register, который демонстрирует основные этапы, необходимые для реализации составного серверного элемента управления ASP.NET. Составной элемент управления использует дочерние элементы управления для создания пользовательского интерфейса UI и выполнения других операций. Поскольку функциональные возможности составного элемента управления основываются на дочерних элементах управления, значительно проще разработать составной элемент управления, чем реализовывать все функциональные возможности элементов управления самому.

В этом примере элемент управления Register использует дочерние элементы управления, чтобы создать пользовательский интерфейс UI для ввода пользовательских данных и регистрации на веб-узле. Пользовательский интерфейс состоит из двух элементов управления TextBox, один из которых используется для ввода имени пользователя а другой — для ввода адреса электронной почты пользователя, и элемента управления Button для передачи информации. Элемент управления Register объединяет также элементы управления RequiredFieldValidator с двумя элементами управления TextBox для гарантирования ввода пользователем имени и адреса электронной почты. Событие Click элемента управления Button вызывается как событие Submit элемента управления Register.

Поведение элемента управления Register основывается на встроенных возможностях дочерних элементов управления. Например, обработка данных обратного процесса элемента управления Register основывается на элементах управления TextBox, обработка событий обратного запроса — на элементе управления Button, а проверка — на элементах управления RequiredFieldValidator.

Код для элемента управления Register описывается ниже в пункте «Рассмотрение кода». При рассмотрении кода для элемента управления Register можно заметить, что большая часть кода относится к созданию и управлению дочерних элементов управления.

// 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.

  • Создание дочерних элементов путем переопределения метода CreateChildControls.

Класс CompositeControl реализует общие функциональные возможности, необходимые для всех составных элементов управления. Он имеет также соответствующий конструктор элементов управления, который обеспечивает отображение дочерних элементов управления на поверхности разработки в визуальном конструкторе.

3257x3ea.alert_note(ru-ru,VS.100).gifПримечание.

Класс CompositeControl — новый класс в ASP.NET 2.0. Если вы создали пользовательские элементы управления в ASP.NET версии 1.0 или 1.1, то придется реализовать интерфейс INamingContainer для создания новой области видимости для дочерних элементов управления. Кроме того, необходимо переопределить свойство Controls и вызвать метод EnsureChildControls. В ASP.NET 2.0 эти и другие шаги выполняются классом CompositeControl.

Необходимо создать дочерние элементы управления в методе CreateChildControls, а не в OnInit или в другой фазе жизненного цикла. Архитектура серверного элемента управления основывается на вызове метода CreateChildControls, когда необходима коллекция Controls, например, при привязке данных (если применимо).

Элемент управления Register также показывает, как предоставлять свойства дочерних элементов управления в качестве свойств высшего уровня. Это полезно, когда нужно разрешить разработчику страницы получать доступ к свойствам дочернего элемента управления. Например, элемент управления Register предоставляет свойство Text дочернего элемента управления Button в качестве своего собственного свойства ButtonText, как показано в следующем коде, взятом из примера:

[
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 и вызывает событие путем присоединения обработчика к событию Click дочернего элемента управления Button.

В следующем примере демонстрируется страница ASP.NET, на которой используется элемент управления Register.

<%@ 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>


Дополнительные сведения о компиляции и использовании примеров пользовательских элементов управления см. в разделе Примеры связывания пользовательского серверного элемента управления.

Показ: