Пример составного веб-элемента управления
Обновлен: Ноябрь 2007
Этот пример показывает, как создать элемент управления с именем Register, который демонстрирует основные этапы, необходимые для реализации составного серверного элемента управления ASP.NET. Составной элемент управления использует дочерние элементы управления для создания пользовательского интерфейса UI и выполнения других операций. Поскольку функциональные возможности составного элемента управления основываются на дочерних элементах управления, значительно проще разработать составной элемент управления, чем реализовывать все функциональные возможности элементов управления самому.
В этом примере элемент управления Register использует дочерние элементы управления, чтобы создать пользовательский интерфейс UI для ввода пользовательских данных и регистрации на веб-узле. Пользовательский интерфейс состоит из двух элементов управления TextBox, один из которых используется для ввода имени пользователя а другой — для ввода адреса электронной почты пользователя, и элемента управления Button для передачи информации. Элемент управления Register объединяет также элементы управления RequiredFieldValidator с двумя элементами управления TextBox для гарантирования ввода пользователем имени и адреса электронной почты. Событие Click элемента управления Button вызывается как событие Submit элемента управления Register.
Поведение элемента управления 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(" ")
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(" ");
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
}
}
Рассмотрение кода
Элемент управления Register выполняет следующие задачи, общие для всех составных элементов управления.
Наследование от класса CompositeControl.
Создание дочерних элементов путем переопределения метода CreateChildControls.
Класс CompositeControl реализует общие функциональные возможности, необходимые для всех составных элементов управления. Он имеет также соответствующий конструктор элементов управления, который обеспечивает отображение дочерних элементов управления на поверхности разработки в визуальном конструкторе.
Примечание. |
---|
Класс 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 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 и вызывает событие путем присоединения обработчика к событию Click дочернего элемента управления Button.
Тестовая страница для элемента управления Register
В следующем примере демонстрируется страница ASP.NET, на которой используется элемент управления Register.
<%@ 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