Gestion d'état de propriété personnalisée, exemple
Mise à jour : novembre 2007
Cet exemple montre comment définir une propriété du contrôle serveur dont le type implémente sa propre gestion d'état. Le contrôle BookNew de l'exemple définit une propriété Author dont le type, StateManagedAuthor, exécute sa propre gestion d'état en implémentant l'interface IStateManager. Le type StateManagedAuthor est décrit dans Gestion d'un état de type personnalisé, exemple.
Le contrôle BookNew de cette rubrique est semblable au contrôle Book décrit dans Propriétés de contrôle serveur, exemple, qui montre comment définir une propriété possédant des sous-propriétés. La différence entre les contrôles BookNew et Book est que le type de la propriété Author dans BookNew délègue la gestion d'état de la propriété Author aux méthodes de gestion d'état du type StateManagedAuthor de la propriété. Par opposition, le contrôle Book gère explicitement l'état de sa propriété Author.
Les méthodes utilisées pour implémenter la gestion d'état (TrackViewState, SaveViewState et LoadViewState) sont décrites plus loin dans la section « Explication du code » de cette rubrique.
Liste du code du contrôle BookNew
Voici la liste de code du contrôle BookNew. La gestion d'état est effectuée par la propriété Author de BookNew et les méthodes de gestion d'état (TrackViewState, SaveViewState et LoadViewState) de la classe StateManagedAuthor.
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}:BookNew runat=""server""> </{0}:BookNew>") _
> _
Public Class BookNew
Inherits WebControl
Private authorValue As StateManagedAuthor
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The name of the author."), _
DesignerSerializationVisibility( _
DesignerSerializationVisibility.Content), _
PersistenceMode(PersistenceMode.InnerProperty) _
> _
Public Overridable ReadOnly Property Author() _
As StateManagedAuthor
Get
If authorValue Is Nothing Then
authorValue = New StateManagedAuthor
If IsTrackingViewState Then
CType(authorValue, IStateManager).TrackViewState()
End If
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 Render(ByVal writer As HtmlTextWriter)
MyBase.AddAttributesToRender(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()
End Sub
#Region "state management"
Protected Overrides Sub LoadViewState( _
ByVal savedState As Object)
Dim p As Pair = TryCast(savedState, Pair)
If p IsNot Nothing Then
MyBase.LoadViewState(p.First)
CType(Author, IStateManager).LoadViewState(p.Second)
Return
End If
MyBase.LoadViewState(savedState)
End Sub
Protected Overrides Function SaveViewState() As Object
Dim baseState As Object = MyBase.SaveViewState
Dim thisState As Object = Nothing
If authorValue IsNot Nothing Then
thisState = _
CType(authorValue, IStateManager).SaveViewState()
End If
If thisState IsNot Nothing Then
Return New Pair(baseState, thisState)
Else
Return baseState
End If
End Function
Protected Overrides Sub TrackViewState()
If authorValue IsNot Nothing Then
CType(Author, IStateManager).TrackViewState()
End If
MyBase.TrackViewState()
End Sub
#End Region
End Class
End Namespace
// BookNew.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}:BookNew runat=\"server\"> </{0}:BookNew>")
]
public class BookNew : WebControl
{
private StateManagedAuthor authorValue;
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The name of the author."),
DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty)
]
public virtual StateManagedAuthor Author
{
get
{
if (authorValue == null)
{
authorValue = new StateManagedAuthor();
if (IsTrackingViewState)
{
((IStateManager)authorValue).TrackViewState();
}
}
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 Render(HtmlTextWriter writer)
{
base.AddAttributesToRender(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();
}
#region state management
protected override void LoadViewState(object savedState)
{
Pair p = savedState as Pair;
if (p != null)
{
base.LoadViewState(p.First);
((IStateManager)Author).LoadViewState(p.Second);
return;
}
base.LoadViewState(savedState);
}
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object thisState = null;
if (authorValue != null)
{
thisState = ((IStateManager)authorValue).SaveViewState();
}
if (thisState != null)
{
return new Pair(baseState, thisState);
}
else
{
return baseState;
}
}
protected override void TrackViewState()
{
if (authorValue != null)
{
((IStateManager)authorValue).TrackViewState();
}
base.TrackViewState();
}
#endregion
}
}
Explication du code
Le contrôle BookNew illustre le modèle permettant d'implémenter des propriétés dont les types gèrent leur propre état en implémentant l'interface IStateManager. En examinant le code du contrôle BookNew dans cette rubrique, vous pourrez juger utile d'examiner également le code du type StateManagedAuthor, le type de la propriété Author du contrôle BookNew. Vous trouverez la liste de code de StateManagedAuthor dans la rubrique Gestion d'un état de type personnalisé, exemple.
BookNew définit la propriété Author comme étant en lecture seule, stockée dans un champ privé de type StateManagedAuthor. Dans l'accesseur de propriété Author, si le champ privé qui correspond à la propriété est null (Nothing en Visual Basic), BookNew lui assigne un nouvel objet StateManagedAuthor. Si BookNew a commencé à suivre l'état, BookNew initialise le suivi d'état sur l'objet StateManagedAuthor nouvellement créé en appelant la méthode TrackViewState de l'objet. Pour plus d'informations sur le suivi, consultez Propriétés de contrôle serveur, exemple.
La propriété Author intervient dans la gestion d'état en appelant les méthodes IStateManager de l'objet StateManagedAuthor à partir de ses propres méthodes de gestion d'état : TrackViewState, SaveViewState et LoadViewState.
Dans la méthode TrackViewState substituée, BookNew appelle la méthode TrackViewState de la classe de base et la méthode TrackViewState de l'objet StateManagedAuthor qui correspond à la propriété Author.
Dans la méthode SaveViewState substituée, BookNew appelle la méthode SaveViewState de la classe de base et la méthode SaveViewState de l'objet StateManagedAuthor qui correspond à la propriété Author. Si la propriété Author a un état à enregistrer, la méthode SaveViewState du contrôle BookNew retourne un objet Pair qui contient l'état de la classe de base et de la propriété Author. Si la propriété Author n'a pas d'état à enregistrer, la méthode ne retourne que l'état retourné par l'appel SaveViewState à la classe de base. En fonction du nombre de propriétés personnalisées qui contribuent à l'état, vous devez retourner des objets de type Pair, Triplet ou Array à partir de SaveViewState. Cela vous permet de récupérer plus facilement les différentes parties de l'état enregistré dans la méthode LoadViewState. Dans ce cas, la classe Pair est utilisée, parce qu'il existe deux éléments, à savoir l'état de classe de base et l'état Author.
Dans la méthode LoadViewState substituée, BookNew implémente l'inverse des opérations qu'il a implémentées dans la méthode LoadViewState. BookNew charge l'état dans la classe de base et dans la propriété Author ou, si la propriété Author n'avait pas d'état à enregistrer, BookNew ne le charge que dans la classe de base. Vous devez toujours appeler la méthode LoadViewState de la classe de base, même si l'état enregistré est null (Nothing en Visual Basic), car la classe de base peut avoir implémenté une autre logique dans cette méthode lorsqu'elle n'a pas d'état à restaurer.
Page de test du contrôle BookNew
L'exemple suivant illustre une page .aspx qui utilise le contrôle BookNew.
<%@ Page Language="C#"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
void Button_Click(object sender, EventArgs e)
{
BookNew1.Author.FirstName = "Bob";
BookNew1.Author.LastName = "Kelly";
BookNew1.Title = "Contoso Stories";
BookNew1.Price = 39.95M;
Button1.Visible = false;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" >
<title>
BookNew test page
</title>
</head>
<body>
<form id="Form1" >
<aspSample:BookNew ID="BookNew1" Runat="server"
BorderStyle="Solid" BorderWidth="1px" Title="Tailspin Stories"
CurrencySymbol="$" BackColor="#FFE0C0" Font-Names="Tahoma"
Price="16" BookType="Fiction">
<Author FirstName="Judy" LastName="Lew" />
</aspSample:BookNew>
<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="BookNewTest.aspx"
Runat="server">
Reload Page</asp:HyperLink>
</form>
</body>
</html>
Génération et utilisation de l'exemple
Compilez le contrôle BookNew avec la classe StateManagedAuthor et la classe StateManagedAuthorConverter décrite dans Gestion d'un état de type personnalisé, exemple.
Pour plus d'informations sur la génération du contrôle et son utilisation dans une page, consultez Exemples de création de contrôles serveur personnalisés.
Voir aussi
Concepts
Gestion d'un état de type personnalisé, exemple
Propriétés de contrôle serveur, exemple