Пример использования свойств серверного веб-элемента управления
Обновлен: Ноябрь 2007
В этом примере демонстрируется создание элемента управления с именем Book, содержащего простые свойства и свойства с вложенными свойствами.
Простое свойство — это свойство строкового типа или типа, который можно легко преобразовать в строку. Простое свойство хранится как атрибут в открывающем теге элемента управления, для чего не требуется никаких действий со стороны разработчика. Свойства типа String и примитивные типы значений в библиотеке классов платформы .NET Framework, такие как Boolean, Int16, Int32 и Enum являются простыми свойствами. Можно добавить код для хранения простого свойства в словаре ViewState для управления состоянием во время обратной передачи.
Свойство считается сложным, если его тип является классом, в свою очередь имеющим свойства, которые называются вложенными свойствами. Например, свойство Font элемента управления WebControl — это класс FontInfo со своими свойствами, такими как Bold и Name. Свойства Bold и Name — это вложенные свойства Font элемента управления WebControl. Структура страницы ASP.NET позволяет хранить вложенные свойства в открывающем теге элемента управления при помощи синтаксиса с использованием дефиса (например, Font-Bold="true"), но при хранении в теге элемента управления вложенные свойства более удобочитаемы (например, <font Bold="true">).
Чтобы визуальный конструктор хранил вложенные свойства как потомки элемента управления, необходимо применить к свойству и его типу несколько атрибутов времени разработки. По умолчанию атрибуты хранятся в теге элемента управления с использованием дефисного синтаксиса. Кроме этого, для свойства с вложенными свойствами необходимо пользовательское управление состоянием для использования просмотра состояния, как описано в подразделе «Рассмотрение кода» далее.
Элемент управления Book, определенный в примере — это элемент управления, который можно использовать в веб-странице для отображения данных о книге или каталоге. Элемент управления Book определяет следующие свойства.
Author, свойство с вложенными свойствами пользовательского типа Author. У типа Author есть собственные свойства, такие как FirstName и LastName, являющиеся вложенными свойствами свойства Author.
BookType, простое свойство с типом пользовательского перечисления BookType. У перечисления BookType могут быть значения, такие как Fiction и NonFiction.
CurrencySymbol, простое свойство встроенного типа String.
Price, простое свойство встроенного типа Decimal.
Title, простое свойство встроенного типа String.
Свойства BookType, CurrencySymbol, Price и Title — простые свойства, поэтому для них не требуются специальные атрибуты при хранении страницы. Структура страницы сохраняет эти свойства по умолчанию как атрибуты в теге элементе управления, как показано в следующем примере:
<aspSample:Book Title="Wingtip Toys Stories"
CurrencySymbol="$"
Price="16"
BookType="Fiction">
</aspSample:Book>
Для свойства Author и свойств класса Author необходимы атрибуты времени разработки для их сохранения в тегах элемента управления, как показано в следующем примере:
<aspSample:Book >
<Author FirstName="Judy" LastName="Lew" />
</aspSample:Book>
Элемент управления Book хранит свои простые свойства в словаре ViewState. Однако элемент управления Book должен реализовать пользовательское управления состоянием свойства Author, чтобы управлять состоянием свойства во время обратной передачи.
Реализация элемента управления Book, пригодная для производственного применения, может определять свойства для других данных, связанных с книгами, например, издателя и дату публикации. Кроме того, свойство Author можно заменить свойством коллекции. Дополнительные свойства о реализации свойства коллекции см. в разделе Пример свойства-коллекции веб-элементов.
![]() |
---|
Разработчик страницы может отключить состояние просмотра для страницы или отдельных элементов управления на странице. Если элемент управления должен поддерживать критичное состояние во время обратной передачи, можно использовать механизм управления состоянием элемента управления, определенный в ASP.NET 2.0. Дополнительные сведения о состоянии элемента управления см. в разделе Сравнительный пример использования состояния элемента управления и состояния просмотра. |
Листинг кода для элемента управления Book
' Book.vb
Option Strict On
Imports System
Imports System.ComponentModel
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), _
DefaultProperty("Title"), _
ToolboxData("<{0}:Book runat=""server""> </{0}:Book>") _
> _
Public Class Book
Inherits WebControl
Private authorValue As Author
Private initialAuthorString As String
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The name of the author."), _
DesignerSerializationVisibility( _
DesignerSerializationVisibility.Content), _
PersistenceMode(PersistenceMode.InnerProperty) _
> _
Public Overridable ReadOnly Property Author() As Author
Get
If (authorValue Is Nothing) Then
authorValue = New Author()
End If
Return authorValue
End Get
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(BookType.NotDefined), _
Description("Fiction or Not") _
> _
Public Overridable Property BookType() As BookType
Get
Dim t As Object = ViewState("BookType")
If t Is Nothing Then t = BookType.NotDefined
Return CType(t, BookType)
End Get
Set(ByVal value As BookType)
ViewState("BookType") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The symbol for the currency."), _
Localizable(True) _
> _
Public Overridable Property CurrencySymbol() As String
Get
Dim s As String = CStr(ViewState("CurrencySymbol"))
If s Is Nothing Then s = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("CurrencySymbol") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue("0.00"), _
Description("The price of the book."), _
Localizable(True) _
> _
Public Overridable Property Price() As Decimal
Get
Dim p As Object = ViewState("Price")
If p Is Nothing Then p = Decimal.Zero
Return CType(p, Decimal)
End Get
Set(ByVal value As Decimal)
ViewState("Price") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The title of the book."), _
Localizable(True) _
> _
Public Overridable 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 RenderContents( _
ByVal writer As HtmlTextWriter)
writer.RenderBeginTag(HtmlTextWriterTag.Table)
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.WriteEncodedText(Title)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.WriteEncodedText(Author.ToString())
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.WriteEncodedText(BookType.ToString())
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.Write(CurrencySymbol)
writer.Write(" ")
writer.Write(String.Format("{0:F2}", Price))
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderEndTag()
End Sub
Protected Overrides Sub LoadViewState( _
ByVal savedState As Object)
MyBase.LoadViewState(savedState)
Dim auth As Author = CType(ViewState("Author"), Author)
If auth IsNot Nothing Then
authorValue = auth
End If
End Sub
Protected Overrides Function SaveViewState() As Object
If authorValue IsNot Nothing Then
Dim currentAuthorString As String = _
authorValue.ToString()
If Not _
(currentAuthorString.Equals(initialAuthorString)) Then
ViewState("Author") = authorValue
End If
End If
Return MyBase.SaveViewState()
End Function
Protected Overrides Sub TrackViewState()
If authorValue IsNot Nothing Then
initialAuthorString = authorValue.ToString()
End If
MyBase.TrackViewState()
End Sub
End Class
End Namespace
// Book.cs
using System;
using System.ComponentModel;
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),
DefaultProperty("Title"),
ToolboxData("<{0}:Book runat=\"server\"> </{0}:Book>")
]
public class Book : WebControl
{
private Author authorValue;
private String initialAuthorString;
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The name of the author."),
DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty),
]
public virtual Author Author
{
get
{
if (authorValue == null)
{
authorValue = new Author();
}
return authorValue;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(BookType.NotDefined),
Description("Fiction or Not"),
]
public virtual BookType BookType
{
get
{
object t = ViewState["BookType"];
return (t == null) ? BookType.NotDefined : (BookType)t;
}
set
{
ViewState["BookType"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The symbol for the currency."),
Localizable(true)
]
public virtual string CurrencySymbol
{
get
{
string s = (string)ViewState["CurrencySymbol"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["CurrencySymbol"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue("0.00"),
Description("The price of the book."),
Localizable(true)
]
public virtual Decimal Price
{
get
{
object price = ViewState["Price"];
return (price == null) ? Decimal.Zero : (Decimal)price;
}
set
{
ViewState["Price"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The title of the book."),
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 RenderContents(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(Title);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(Author.ToString());
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(BookType.ToString());
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(CurrencySymbol);
writer.Write(" ");
writer.Write(String.Format("{0:F2}", Price));
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
Author auth = (Author)ViewState["Author"];
if (auth != null)
{
authorValue = auth;
}
}
protected override object SaveViewState()
{
if (authorValue != null)
{
String currentAuthorString = authorValue.ToString();
if (!(currentAuthorString.Equals(initialAuthorString)))
{
ViewState["Author"] = authorValue;
}
}
return base.SaveViewState();
}
protected override void TrackViewState()
{
if (authorValue != null)
{
initialAuthorString = authorValue.ToString();
}
base.TrackViewState();
}
}
}
Рассмотрение кода
Атрибуты DesignerSerializationVisibilityAttribute и PersistenceModeAttribute, примененные к свойству Author элемента управления Book, описываются в разделе Пример свойства-коллекции веб-элементов. Эти атрибуты необходимы для сериализации и хранения свойств класса Author.
Механизм состояния просмотра ссылается на методы, используемые ASP.NET для поддержания состояния во время обратной передачи. Механизм выполняет сериализацию состояния страницы и его дерева элементов управления в строковое представление в конце обработки страницы и выполняет десериализацию во время обратной передачи. По умолчанию страница передает строки обозревателю как скрытые поля. Дополнительные сведения см. в разделе Общие сведения об управлении состоянием ASP.NET.
Для управления состоянием простого свойства оно определяется как простое свойство, доступное для чтения и записи, которое хранится в свойстве ViewState элемента управления. Элемент управления Book определяет свои простые свойства (BookType, CurrencySymbol, Price и Title) этим способом. Управление состоянием свойств, хранимых в свойстве ViewState, происходит без участия разработчика.
Для управления свойством с вложенными свойствами можно определить его, как доступное только для чтения и написать код для управления состоянием объекта. Для этого необходимо переопределить следующие методы.
TrackViewState, чтобы дать команду элементу управления для начала отслеживания изменения свойств после инициализации.
SaveViewState, для сохранения свойства (если оно изменилось) в конце запроса страницы.
LoadViewState, для загрузки сохраненного состояния в свойство при обратной передаче.
Примечание.
Помимо способов, описанных здесь, есть и другие методы управления состоянием сложных свойств. Можно расширить метод, используемый в разделе Пошаговое руководство. Создание и использование пользовательского серверного элемента управления, изменяя состояние просмотра при каждом изменении свойства. Также можно управлять состоянием в классе свойства, как показано в разделе Пример управления состоянием настраиваемого свойства.
Тип свойства ViewState, StateBag — это словарь со встроенным управлением состоянием. Класс StateBag реализует интерфейс IStateManager, определяющий методы TrackViewState, SaveViewState и LoadViewState. Класс StateBag реализует эти методы для запуска отслеживания изменений свойств элемента управления после инициализации, сохраняет измененные элементы в конце запроса страницы и загружает сохраненное состояние при обратной передаче. Метод StateBag отслеживает элементы, отмечая элемент, как измененный, если он устанавливается после выполнения метода OnInit для запроса страницы. Например, если любой код на странице, выполняемый после ее инициализации задает свойство Title элемента управления Book, изменения вносятся в ViewState["Title"]. Как следствие, значение, сохраненное, как ключ «Title» в свойстве ViewState помечается как измененное. Дополнительные сведения см. в разделе Общие сведения о жизненном цикле веб-страниц ASP.NET.
Элемент управления Book задает свойство Author как доступное только для чтения property и реализует пользовательское управление состоянием, как в следующем примере:
В методе TrackViewState элемент управления Book сначала сохраняет первоначальное свойство Author в строку и затем запускает отслеживание состояние, вызывая метод TrackViewState базового класса.
В методе SaveViewState элемент управления Book определяет, отличается ли значение свойства Author от первоначального. Если свойство изменено, элемент управления Book сохраняет свойство Author в словаре ViewState, используя ключ «Author». Затем элемент управления Book вызывает метод SaveViewState базового класса. Так как отслеживание состояния включено, объект Author, сохраненный в свойстве ViewState, автоматически отмечается как измененный и записывается в состояние просмотра базового класса.
В методе LoadViewState элемент управления Book сначала вызывает метод LoadViewState базового класса. При этом словарь ViewState автоматически восстанавливается. Затем элемент управления Book определяет, есть ли в словаре ViewState элемент, сохраненный с ключом «Author». Если элемент найден, элемент управления загружает значение состояния просмотра в свойство Author.
В типе Author (определенном в коде далее) есть пользовательский преобразователь типов, позволяющий хранить экземпляр Author в состоянии просмотра. Он преобразует экземпляр типа Author в строку и обратно. Определение преобразователя типов позволяет задавать вложенные свойства Author в визуальном конструкторе. Пользовательский преобразователь типов описывается в разделе Пример преобразователя типов. Типы, которые можно хранить в состоянии просмотра, ограничены классом LosFormatter, используемым ASP.NET для сериализации состояния просмотра. Наиболее эффективно сериализуются типы String, примитивные типы значения в библиотеке классов платформы .NET Framework, такие как Boolean, Int16, Int32, Enum, Pair, Triplet, Array, ArrayList и Hashtable, а также все типы, содержащие эти примитивные типы. Кроме этого в состоянии просмотра можно хранить пользовательские типы с определенными преобразователями типов, такие как Pair, Triplet, Array, ArrayList и Hashtable. При определении сериализации состояния просмотра для пользовательского элемента управления необходимо преобразовать данные элемента управления в один из этих типов. При хранении в состоянии просмотра типов, несовместимых с механизмом сериализации элемент управления может скомпилироваться, но выдаст ошибку во время выполнения. Наконец, сериализуемые типы (то есть типы, реализующие интерфейс ISerializable, или отмеченные атрибутом SerializableAttribute) можно хранить в состоянии просмотра, но сериализация для этих типов намного медленнее, чем для примитивных типов.
Объект состояния, передаваемый элементом управления для сериализации — это состояние просмотра элемента управления. Свойство ViewState элемента управления — это только часть состояния просмотра элемента управления, которая автоматически участвует в механизме состояния просмотра, причем для этого не требуются какие-либо действия со стороны разработчика. Класс Control реализует логику сохранения и загрузки измененных элементов в словаре ViewState в его методах SaveViewState и LoadViewState. Другая часть или части состояния просмотра — это дополнительные объекты, которые разработчик (и базовый класс элемента управления) сохраняются в состоянии просмотра при переопределении метода SaveViewState. При переопределении методов SaveViewState и LoadViewState следует вызвать соответствующие методы базового класса.
Листинг кода класса Author
Применение атрибута NotifyParentPropertyAttribute к свойствам FirstName, LastName и MiddleName и присвоение аргументу атрибута значения true приводит к тому, что визуальный конструктор применяет и сериализует изменения этих свойств в их родительское свойство (экземпляр Author).
' Author.vb
Option Strict On
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Globalization
Imports System.Web.UI
Namespace Samples.AspNet.VB.Controls
< _
TypeConverter(GetType(AuthorConverter)) _
> _
Public Class Author
Dim firstNameValue As String
Dim lastNameValue As String
Dim middleNameValue As String
Public Sub New()
Me.New(String.Empty, String.Empty, String.Empty)
End Sub
Public Sub New(ByVal firstname As String, _
ByVal lastname As String)
Me.New(firstname, String.Empty, lastname)
End Sub
Public Sub New(ByVal firstname As String, _
ByVal middlename As String, ByVal lastname As String)
firstNameValue = firstname
middleNameValue = middlename
lastNameValue = lastname
End Sub
< _
Category("Behavior"), _
DefaultValue(""), _
Description("First name of author."), _
NotifyParentProperty(True) _
> _
Public Overridable Property FirstName() As String
Get
Return firstNameValue
End Get
Set(ByVal value As String)
firstNameValue = value
End Set
End Property
< _
Category("Behavior"), _
DefaultValue(""), _
Description("Last name of author."), _
NotifyParentProperty(True) _
> _
Public Overridable Property LastName() As String
Get
Return lastNameValue
End Get
Set(ByVal value As String)
lastNameValue = value
End Set
End Property
< _
Category("Behavior"), _
DefaultValue(""), _
Description("Middle name of author."), _
NotifyParentProperty(True) _
> _
Public Overridable Property MiddleName() As String
Get
Return middleNameValue
End Get
Set(ByVal value As String)
middleNameValue = value
End Set
End Property
Public Overrides Function ToString() As String
Return ToString(CultureInfo.InvariantCulture)
End Function
Public Overloads Function ToString( _
ByVal culture As CultureInfo) As String
Return TypeDescriptor.GetConverter( _
Me.GetType()).ConvertToString(Nothing, culture, Me)
End Function
End Class
End Namespace
// Author.cs
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI;
namespace Samples.AspNet.CS.Controls
{
[
TypeConverter(typeof(AuthorConverter))
]
public class Author
{
private string firstnameValue;
private string lastnameValue;
private string middlenameValue;
public Author()
:
this(String.Empty, String.Empty, String.Empty)
{
}
public Author(string firstname, string lastname)
:
this(firstname, String.Empty, lastname)
{
}
public Author(string firstname,
string middlename, string lastname)
{
firstnameValue = firstname;
middlenameValue = middlename;
lastnameValue = lastname;
}
[
Category("Behavior"),
DefaultValue(""),
Description("First name of author."),
NotifyParentProperty(true),
]
public virtual String FirstName
{
get
{
return firstnameValue;
}
set
{
firstnameValue = value;
}
}
[
Category("Behavior"),
DefaultValue(""),
Description("Last name of author."),
NotifyParentProperty(true)
]
public virtual String LastName
{
get
{
return lastnameValue;
}
set
{
lastnameValue = value;
}
}
[
Category("Behavior"),
DefaultValue(""),
Description("Middle name of author."),
NotifyParentProperty(true)
]
public virtual String MiddleName
{
get
{
return middlenameValue;
}
set
{
middlenameValue = value;
}
}
public override string ToString()
{
return ToString(CultureInfo.InvariantCulture);
}
public string ToString(CultureInfo culture)
{
return TypeDescriptor.GetConverter(
GetType()).ConvertToString(null, culture, this);
}
}
}
Листинг кода перечисления BookType
' BookType.vb
Option Strict On
Imports System
Namespace Samples.AspNet.VB.Controls
Public Enum BookType
NotDefined = 0
Fiction = 1
NonFiction = 2
End Enum
End Namespace
// BookType.cs
using System;
namespace Samples.AspNet.CS.Controls
{
public enum BookType
{
NotDefined = 0,
Fiction = 1,
NonFiction = 2
}
}
Тестовая страница для элемента управления Book
В следующем примере показана ASPX-страница, использующая элемент управления Book.
<%@ Page Language="C#" Debug="true" Trace="true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Button_Click(object sender, EventArgs e)
{
Book1.Author.FirstName = "Bob";
Book1.Author.LastName = "Kelly";
Book1.Title = "Contoso Stories";
Book1.Price = 39.95M;
Button1.Visible = false;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>
Book test page
</title>
</head>
<body>
<form id="Form1" runat="server">
<aspSample:Book ID="Book1" Runat="server"
Title="Tailspin Toys Stories" CurrencySymbol="$"
BackColor="#FFE0C0" Font-Names="Tahoma"
Price="16" BookType="Fiction">
<Author FirstName="Judy" LastName="Lew" />
</aspSample:Book>
<br />
<asp:Button ID="Button1" OnClick="Button_Click"
Runat="server" Text="Change" />
<asp:Button ID="Button2" Runat="server" Text="Refresh" />
<br />
<br />
<asp:HyperLink ID="Hyperlink1" href="BookTest.aspx"
Runat="server">
Reload Page</asp:HyperLink>
</form>
</body>
</html>
Построение и использование примера
Выполните компиляцию классов в этом примере с классом AuthorConverter, описанном в подразделе Пример преобразователя типов.
Дополнительные сведения о компиляции и использовании примеров пользовательских элементов управления см. в разделе Примеры связывания пользовательского серверного элемента управления.
См. также
Основные понятия
Типы значений в системе общих типов CTS
Ссылки
Другие ресурсы
Разработка пользовательских серверных элементов управления ASP.NET