Partager via


Gestion d'un état de type personnalisé, exemple

Mise à jour : novembre 2007

Cet exemple montre comment permettre à une propriété complexe (une propriété dont le type est une classe possédant elle-même des propriétés) de participer à l'état d'affichage d'ASP.NET en implémentant l'interface IStateManager. Comme il est décrit dans Propriétés de contrôle serveur, exemple, vous pouvez utiliser la propriété ViewState de votre contrôle pour gérer l'état de propriétés simples. Toutefois, vous devez implémenter la propriété comme étant en lecture seule pour fournir la gestion d'état d'une propriété de collection ou d'une propriété possédant des sous-propriétés. Dans le cadre du type de propriété, vous devez typiquement implémenter IStateManager.

Le type StateManagedAuthor défini dans cet exemple montre comment implémenter IStateManager. La classe StateManagedAuthor est un type complexe qui possède lui-même des sous-propriétés telles que FirstName et LastName. La propriété Author du contrôle BookNew décrite dans Gestion d'état de propriété personnalisée, exemple est de type StateManagedAuthor.

L'implémentation de l'interface IStateManager dans StateManagedAuthor est décrite plus loin dans la section « Explication du code » de cette rubrique.

Liste du code de la classe StateManagedAuthor

' StateManagedAuthor.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(StateManagedAuthorConverter)) _
    > _
    Public Class StateManagedAuthor
        Implements IStateManager
        Private isTrackingViewStateValue As Boolean
        Private viewStateValue As StateBag

        Public Sub New()
            Me.New(String.Empty, String.Empty, String.Empty)
        End Sub

        Public Sub New(ByVal first As String, ByVal last As String)
            Me.New(first, String.Empty, last)
        End Sub

        Public Sub New(ByVal first As String, ByVal middle As String, _
            ByVal last As String)
            FirstName = first
            MiddleName = middle
            LastName = last
        End Sub

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("First name of author"), _
        NotifyParentProperty(True) _
        > _
        Public Overridable Property FirstName() As String
            Get
                Dim s As String = CStr(ViewState("FirstName"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("FirstName") = value
            End Set
        End Property

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Last name of author"), _
        NotifyParentProperty(True) _
        > _
        Public Overridable Property LastName() As String
            Get
                Dim s As String = CStr(ViewState("LastName"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("LastName") = value
            End Set
        End Property

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Middle name of author"), _
        NotifyParentProperty(True) _
        > _
        Public Overridable Property MiddleName() As String
            Get
                Dim s As String = CStr(ViewState("MiddleName"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("MiddleName") = value
            End Set
        End Property

        Protected Overridable ReadOnly Property ViewState() _
            As StateBag
            Get
                If viewStateValue Is Nothing Then
                    viewStateValue = New StateBag(False)

                    If isTrackingViewStateValue Then
                        CType(viewStateValue, _
                        IStateManager).TrackViewState()
                    End If
                End If
                Return viewStateValue
            End Get
        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

#Region "IStateManager implementation"
        Public ReadOnly Property IsTrackingViewState() As Boolean _
            Implements IStateManager.IsTrackingViewState
            Get
                Return isTrackingViewStateValue
            End Get
        End Property

        Public Sub LoadViewState(ByVal savedState As Object) _
            Implements IStateManager.LoadViewState
            If savedState IsNot Nothing Then
                CType(ViewState, _
                    IStateManager).LoadViewState(savedState)
            End If
        End Sub

        Public Function SaveViewState() As Object _
            Implements IStateManager.SaveViewState
            Dim savedState As Object = Nothing
            If viewStateValue IsNot Nothing Then
                savedState = CType(viewStateValue, _
                    IStateManager).SaveViewState
            End If
            Return savedState
        End Function

        Public Sub TrackViewState() _
            Implements IStateManager.TrackViewState
            isTrackingViewStateValue = True
            If viewStateValue IsNot Nothing Then
                CType(viewStateValue, IStateManager).TrackViewState()
            End If
        End Sub
#End Region

        Protected Sub SetDirty()
            viewStateValue.SetDirty(True)
        End Sub
    End Class
End Namespace
// StateManagedAuthor.cs
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI;

namespace Samples.AspNet.CS.Controls
{
    [
    TypeConverter(typeof(StateManagedAuthorConverter))
    ]
    public class StateManagedAuthor : IStateManager
    {
        private bool _isTrackingViewState;
        private StateBag _viewState;

        public StateManagedAuthor()
            :
            this(String.Empty, String.Empty, String.Empty)
        {
        }

        public StateManagedAuthor(string first, string last)
            :
            this(first, String.Empty, last)
        {
        }

        public StateManagedAuthor(string first, string middle, string last)
        {
            FirstName = first;
            MiddleName = middle;
            LastName = last;
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("First name of author"),
        NotifyParentProperty(true)
        ]
        public virtual String FirstName
        {
            get
            {
                string s = (string)ViewState["FirstName"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["FirstName"] = value;
            }
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Last name of author"),
        NotifyParentProperty(true)
        ]
        public virtual String LastName
        {
            get
            {
                string s = (string)ViewState["LastName"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["LastName"] = value;
            }
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Middle name of author"),
        NotifyParentProperty(true)
        ]
        public virtual String MiddleName
        {
            get
            {
                string s = (string)ViewState["MiddleName"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["MiddleName"] = value;
            }
        }

        protected virtual StateBag ViewState
        {
            get
            {
                if (_viewState == null)
                {
                    _viewState = new StateBag(false);

                    if (_isTrackingViewState)
                    {
                        ((IStateManager)_viewState).TrackViewState();
                    }
                }
                return _viewState;
            }
        }


        public override string ToString()
        {
            return ToString(CultureInfo.InvariantCulture);
        }

        public string ToString(CultureInfo culture)
        {
            return TypeDescriptor.GetConverter(
                GetType()).ConvertToString(null, culture, this);
        }

        #region IStateManager implementation
        bool IStateManager.IsTrackingViewState
        {
            get
            {
                return _isTrackingViewState;
            }
        }

        void IStateManager.LoadViewState(object savedState)
        {
            if (savedState != null)
            {
                ((IStateManager)ViewState).LoadViewState(savedState);
            }
        }

        object IStateManager.SaveViewState()
        {
            object savedState = null;

            if (_viewState != null)
            {
                savedState =
                   ((IStateManager)_viewState).SaveViewState();
            }
            return savedState;
        }

        void IStateManager.TrackViewState()
        {
            _isTrackingViewState = true;

            if (_viewState != null)
            {
                ((IStateManager)_viewState).TrackViewState();
            }
        }
        #endregion

        internal void SetDirty()
        {
            _viewState.SetDirty(true);
        }
    }
}

Explication du code

La classe StateManagedAuthor illustre le modèle permettant d'implémenter l'interface IStateManager couramment utilisée par les types complexes d'ASP.NET. StateManagedAuthor définit une propriété nommée ViewState, stockée dans une variable privée de type StateBag et nommée viewState en C# et viewStateValue en Visual Basic. La propriété ViewState reproduit la propriété ViewState de la classe Control. StateManagedAuthor stocke ses propriétés dans son dictionnaire ViewState, de la même manière qu'un contrôle stocke ses propriétés simples dans le dictionnaire ViewState de la classe Control.

L'interface IStateManager possède une propriété, IsTrackingViewState, et trois méthodes : TrackViewState, SaveViewState et LoadViewState. Les membres de l'interface IStateManager ont la même sémantique que les méthodes correspondantes dans la classe Control.

La propriété IsTrackingViewState active un type qui implémente IStateManager pour la coordination avec le suivi d'état du contrôle dans lequel le type est utilisé. La classe StateManagedAuthor utilise un champ privé Boolean (isTrackingViewState en C# et isTrackingViewStateValue en Visual Basic) pour stocker cette propriété. Dans son implémentation de TrackViewState, StateManagedAuthor définit isTrackingViewState ou isTrackingViewStateValue en true. Il appelle également la méthode IStateManager.TrackViewState du champ privé viewState ou viewStateValue qui correspond à la propriété ViewState. La méthode TrackViewState démarre le suivi des modifications des éléments stockés dans la propriété ViewState. Cela signifie que si un élément du dictionnaire ViewState est défini après l'appel de TrackViewState sur ViewState, cet élément est marqué automatiquement comme étant modifié.

Dans son implémentation de la méthode SaveViewState, StateManagedAuthor n'appelle que la méthode correspondante de son champ privé viewState ou viewStateValue. De la même façon, dans son implémentation de la méthode LoadViewState,.StateManagedAuthor n'appelle que la méthode correspondante de sa propriété ViewState Comme il est décrit dans Propriétés de contrôle serveur, exemple, le type StateBag de la propriété ViewState implémente IStateManager et est un dictionnaire avec gestion d'état intégrée.

Lorsque vous utilisez un type qui implémente IStateManager dans votre contrôle, vous vous appuyez sur ce type pour qu'il conserve son propre état et vous appelez ses méthodes de gestion d'état à partir des méthodes TrackViewState, SaveViewState et LoadViewState de votre contrôle. Le contrôle BookNew décrit dans Gestion d'état de propriété personnalisée, exemple appelle donc les méthodes TrackViewState, SaveViewState et LoadViewState de StateManagedAuthor à partir de sa propre implémentation de ces méthodes.

Liste du code de la classe StateManagedAuthorConverter

StateManagedAuthorConverter de la liste de code suivante est le convertisseur de type associé à StateManagedAuthor au moyen de l'attribut TypeConverterAttribute. La classe StateManagedAuthorConverter permet des conversions depuis le type String vers le type StateManagedAuthor et vice-versa, comme décrit dans l'exemple Convertisseur de type, exemple. StateManagedAuthorConverter est utilisé dans cet exemple pour afficher le nom complet de l'auteur dans la méthode Render de la classe BookNew.

Remarque :

Le type StateManagedAuthor n'a pas besoin de convertisseur de type pour la gestion d'état. StateManagedAuthorConverter est fourni en tant que classe utilitaire facultative fournissant des conversions de chaînes en valeurs. Lorsque vous implémentez un convertisseur de type pour un type personnalisé, vous devez substituer la méthode ToString de votre type pour appeler le convertisseur de type et retourner une représentation sous forme de chaîne, comme indiqué dans la liste du code de StateManagedAuthor.

' StateManagedAuthorConverter.vb
Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Globalization
Imports System.Reflection

Namespace Samples.AspNet.VB.Controls
    Public Class StateManagedAuthorConverter
        Inherits ExpandableObjectConverter

        Public Overrides Function CanConvertFrom( _
        ByVal context As ITypeDescriptorContext, _
        ByVal sourceType As Type) As Boolean
            If sourceType Is GetType(String) Then
                Return True
            End If
            Return MyBase.CanConvertFrom(context, sourceType)
        End Function

        Public Overrides Function CanConvertTo( _
        ByVal context As ITypeDescriptorContext, _
        ByVal destinationType As Type) As Boolean
            If destinationType Is GetType(String) Then
                Return True
            End If
            Return MyBase.CanConvertTo(context, destinationType)
        End Function


        Public Overrides Function ConvertFrom( _
            ByVal context As ITypeDescriptorContext, _
            ByVal culture As CultureInfo, ByVal value As Object) _
            As Object
            If value Is Nothing Then
                Return New StateManagedAuthor()
            End If

            If (TypeOf value Is String) Then
                Dim s As String = CStr(value)
                If s.Length = 0 Then
                    Return New StateManagedAuthor()
                End If

                Dim parts() As String = s.Split(" ".ToCharArray)

                If (parts.Length < 2) Or (parts.Length > 3) Then
                    Throw New ArgumentException( _
                        "Name must have 2 or 3 parts.", "value")
                End If

                If parts.Length = 2 Then
                    Return New StateManagedAuthor(parts(0), parts(1))
                End If

                If parts.Length = 3 Then
                    Return New StateManagedAuthor(parts(0), _
                        parts(1), parts(2))
                End If
            End If
            Return MyBase.ConvertFrom(context, culture, value)
        End Function

        Public Overrides Function ConvertTo( _
        ByVal context As ITypeDescriptorContext, _
        ByVal culture As CultureInfo, ByVal value As Object, _
        ByVal destinationType As Type) As Object
            If value IsNot Nothing Then
                If Not (TypeOf value Is StateManagedAuthor) Then
                    Throw New ArgumentException( _
                        "Name must have 2 or 3 parts.", "value")
                End If
            End If

            If destinationType Is GetType(String) Then
                If value Is Nothing Then
                    Return String.Empty
                End If

                Dim auth As StateManagedAuthor = _
                    CType(value, StateManagedAuthor)

                If auth.MiddleName <> String.Empty Then
                    Return String.Format("{0} {1} {2}", _
                    auth.FirstName, _
                    auth.MiddleName, _
                    auth.LastName)
                Else
                    Return String.Format("{0} {1}", _
                        auth.FirstName, _
                        auth.LastName)
                End If
            End If

            Return MyBase.ConvertTo(context, culture, value, _
                destinationType)
        End Function
    End Class
End Namespace
// StateManagedAuthorConverter.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;

namespace Samples.AspNet.CS.Controls
{
    public class StateManagedAuthorConverter :
        ExpandableObjectConverter
    {
        public override bool CanConvertFrom(
            ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(
            ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }
            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertFrom( 
            ITypeDescriptorContext context,
            CultureInfo culture, object value)
        {
            if (value == null)
            {
                return new StateManagedAuthor();
            }

            if (value is string)
            {
                string s = (string)value;
                if (s.Length == 0)
                {
                    return new StateManagedAuthor();
                }

                string[] parts = s.Split(' ');

                if ((parts.Length < 2) || (parts.Length > 3))
                {
                    throw new ArgumentException(
                        "Name must have 2 or 3 parts.", "value");
                }

                if (parts.Length == 2)
                {
                    return new StateManagedAuthor(parts[0], parts[1]);
                }

                if (parts.Length == 3)
                {
                    return new StateManagedAuthor(parts[0], 
                         parts[1], parts[2]);
                }
            }

            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context,
            CultureInfo culture, object value, Type destinationType)
        {
            if (value != null)
            {
                if (!(value is StateManagedAuthor))
                {
                    throw new ArgumentException(
                        "Name must have 2 or 3 parts.", "value");
                }
            }

            if (destinationType == typeof(string))
            {
                if (value == null)
                {
                    return String.Empty;
                }

                StateManagedAuthor auth = (StateManagedAuthor)value;

                if (auth.MiddleName != String.Empty)
                {
                    return String.Format("{0} {1} {2}",
                        auth.FirstName,
                        auth.MiddleName,
                        auth.LastName);
                }
                else
                {
                    return String.Format("{0} {1}",
                        auth.FirstName,
                        auth.LastName);
                }
            }

            return base.ConvertTo(context, culture,
                value, destinationType);
        }
    }
}

Génération et utilisation de l'exemple

Compilez les classes StateManagedAuthor et StateManagedAuthorConverter répertoriées dans cette rubrique avec le contrôle BookNew répertorié dans Gestion d'état de propriété personnalisée, exemple et l'énumération BookType répertoriée dans Propriétés de contrôle serveur, exemple.

Pour plus d'informations sur la compilation et l'utilisation des exemples de contrôles personnalisés, consultez Exemples de création de contrôles serveur personnalisés.

Voir aussi

Concepts

Gestion d'état de propriété personnalisée, exemple

Propriétés de contrôle serveur, exemple

Exemples de création de contrôles serveur personnalisés

Autres ressources

Développement de contrôles serveur ASP.NET personnalisés