Partager via


Implémentation d'un convertisseur de type

Un convertisseur de type peut être utilisé pour convertir des valeurs entre des types de données et pour aider à configurer des propriétés au moment du design en fournissant une conversion de texte en valeur ou une liste déroulante de valeurs dans laquelle une sélection peut être effectuée. S'il est correctement configuré, un convertisseur de type peut produire du code de configuration de propriétés à l'aide de InstanceDescriptor et des objets System.Reflection pour fournir au système de sérialisation du concepteur les informations nécessaires pour créer le code qui initialise la propriété au moment de l'exécution.

Convertisseurs de type pour la conversion en valeur

Des convertisseurs de type peuvent être utilisés pour des conversions de chaîne en valeur vers ou à partir de types de données pris en charge au moment du design et de l'exécution. Dans un hôte tel qu'une fenêtre de propriétés d'un concepteur de formulaires, les convertisseurs de type permettent de représenter une valeur de propriété sous la forme de texte à l'attention de l'utilisateur et ils peuvent convertir le texte entré par l'utilisateur dans une valeur du type de données approprié.

La plupart des types de données natifs (Int32, String, types énumération, etc.) possèdent des convertisseurs de type par défaut qui fournissent des conversions de chaîne en valeur et effectuent des vérifications de validation. Les convertisseurs de type par défaut se trouvent dans l'espace de noms System.ComponentModel et sont appelés NomConvertisseurTypeConverter. Vous pouvez étendre un convertisseur de type si la fonctionnalité par défaut n'est pas adaptée à vos besoins ou implémenter un convertisseur de type personnalisé si vous définissez un type personnalisé auquel aucun convertisseur de type n'est associé.

**Remarque   **Un attribut TypeConverterAttribute est généralement appliqué à une propriété ou à des données membres afin de les associer à un convertisseur de type. Si TypeConverterAttribute est appliqué à un type, il ne doit pas être réappliqué aux propriétés ou aux données membres de ce type.

L'implémentation d'un convertisseur de type est indépendante de toute fonctionnalité de l'interface utilisateur. Par conséquent, le même convertisseur de type peut être appliqué à la fois dans Windows Forms et dans Web Forms.

Pour implémenter un convertisseur de type simple pouvant convertir une chaîne en type Point

  1. Définissez une classe qui dérive de System.ComponentModel.TypeConverter.
  2. Substituez la méthode CanConvertFrom spécifiant le type que le convertisseur peut convertir. Cette méthode est surchargée.
  3. Substituez la méthode ConvertFrom qui implémente la conversion. Cette méthode est surchargée.
  4. Substituez la méthode CanConvertTo qui spécifie le type vers lequel le convertisseur peut effectuer la conversion. Il n'est pas nécessaire de substituer cette méthode pour effectuer la conversion en un type string. Cette méthode est surchargée.
  5. Substituez la méthode ConvertTo qui implémente la conversion. Cette méthode est surchargée.
  6. Substituez la méthode IsValid qui effectue la validation. Cette méthode est surchargée.

L'exemple de code suivant implémente un convertisseur de type qui convertit un type String en type System.Drawing.Point et un type System.Drawing.Point en type String. Les méthodes CanConvertTo et IsValid ne sont pas substituées dans cet exemple.

Option Explicit 
Option Strict

Imports System
Imports System.ComponentModel
Imports System.Globalization
Imports System.Drawing

Public Class PointConverter
   Inherits TypeConverter
   
   ' Overrides the CanConvertFrom method of TypeConverter.
   ' The ITypeDescriptorContext interface provides the context for the
   ' conversion. Typically, this interface is used at design time to 
   ' provide information about the design-time container.
   Public Overrides Overloads Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
      If sourceType Is GetType(String) Then
         Return True
      End If
      Return MyBase.CanConvertFrom(context, sourceType)
   End Function
   
   ' Overrides the ConvertFrom method of TypeConverter.
   Public Overrides Overloads Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object
      If TypeOf value Is String Then
         Dim v As String() = CStr(value).Split(New Char() {","c})
         Return New Point(Integer.Parse(v(0)), Integer.Parse(v(1)))
      End If
      Return MyBase.ConvertFrom(context, culture, value)
   End Function
   
   ' Overrides the ConvertTo method of TypeConverter.
   Public Overrides Overloads Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
      If destinationType Is GetType(String) Then
         Return CType(value, Point).X & "," & CType(value, Point).Y
      End If
      Return MyBase.ConvertTo(context, culture, value, destinationType)
   End Function
End Class
[C#]
using System;
using System.ComponentModel;
using System.Globalization;
using System.Drawing;

public class PointConverter : TypeConverter {
   // Overrides the CanConvertFrom method of TypeConverter.
   // The ITypeDescriptorContext interface provides the context for the
   // conversion. Typically, this interface is used at design time to 
   // provide information about the design-time container.
   public override bool CanConvertFrom(ITypeDescriptorContext context, 
      Type sourceType) {
      
      if (sourceType == typeof(string)) {
         return true;
      }
      return base.CanConvertFrom(context, sourceType);
   }
   // Overrides the ConvertFrom method of TypeConverter.
   public override object ConvertFrom(ITypeDescriptorContext context, 
      CultureInfo culture, object value) {
      if (value is string) {
         string[] v = ((string)value).Split(new char[] {','});
         return new Point(int.Parse(v[0]), int.Parse(v[1]));
      }
      return base.ConvertFrom(context, culture, value);
   }
   // Overrides the ConvertTo method of TypeConverter.
   public override object ConvertTo(ITypeDescriptorContext context, 
      CultureInfo culture, object value, Type destinationType) {  
      if (destinationType == typeof(string)) {
         return ((Point)value).X + "," + ((Point)value).Y;
      }
      return base.ConvertTo(context, culture, value, destinationType);
   }
}

Convertisseurs de type qui fournissent une liste de valeurs standard dans une grille des propriétés

Un convertisseur de type peut fournir une liste de valeurs pour un type dans un contrôle de grille des propriétés. Lorsqu'un convertisseur de type fournit un ensemble de valeurs standard pour un type, le champ d'entrée des valeurs pour une propriété du type associé dans un contrôle de grille des propriétés affiche une flèche bas ; lorsque vous sélectionnez cette flèche, vous obtenez une liste de valeurs à affecter à la propriété.

Lorsqu'une propriété du type auquel ce convertisseur de type est associé est sélectionnée dans une fenêtre des propriétés d'un environnement au moment du design, le champ d'entrée des valeurs contient un bouton qui affiche une liste déroulante des valeurs standard du type de propriété dans laquelle vous pouvez effectuer une sélection.

Pour implémenter un convertisseur de type simple qui fournit une liste déroulante de valeurs standard dans une fenêtre des propriétés

  1. Définissez une classe qui dérive de System.ComponentModel.TypeConverter.
  2. Substituez la méthode GetStandardValuesSupported et retournez true.
  3. Substituez la méthode GetStandardValues et retournez StandardValuesCollection qui contient les valeurs standard pour le type de propriété. Les valeurs standard d'un type de propriété doivent être de type String.
  4. Substituez la méthode CanConvertFrom et retournez true pour une valeur de paramètre sourceType de type String.
  5. Substituez la méthode ConvertFrom et retournez la valeur appropriée de la propriété sur la base du paramètre value.
  6. Appliquez TypeConverterAttribute qui indique le type de votre convertisseur de type au type pour lequel vous fournissez un ensemble de valeurs standard.

L'exemple suivant illustre un convertisseur de type qui fournit une liste de valeurs standard à un contrôle de grille des propriétés pour une propriété à laquelle le type est associé. Le convertisseur de type pris en exemple prend en charge des propriétés de type entier avec lesquelles il a été associé. Pour utiliser l'exemple dans Visual Studio .NET, compilez le code dans une bibliothèque de classes et ajoutez le composant IntStandardValuesControl à la boîte à outils. Ajoutez une instance de IntStandardValuesControl à un formulaire en mode design et faites défiler la fenêtre Propriétés pour atteindre la propriété TestInt pendant que le contrôle est sélectionné. Lorsque vous sélectionnez le champ d'entrée des valeurs de la propriété, une flèche bas apparaît. Lorsque vous cliquez sur cette flèche, une liste déroulante de valeurs standard s'affiche. Si vous entrez une valeur entière, celle-ci est ajoutée à la liste des valeurs standard et la valeur spécifiée est affectée à la propriété.

using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;

namespace StandardValuesTest
{  
    public class StandardValuesIntConverter : System.ComponentModel.TypeConverter
    {
        private ArrayList values;
        public StandardValuesIntConverter()
        {
            // Initializes the standard values list with defaults.
            values = new ArrayList(new int[] { 1, 2, 3, 4, 5 });
        }

        // Indicates this converter provides a list of standard values.
        public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context)
        {
            return true;
        }

        // Returns a StandardValuesCollection of standard value objects.
        public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context)
        {        
            // Passes the local integer array.
            StandardValuesCollection svc = 
                new StandardValuesCollection(values);       
            return svc;
        }

        // Returns true for a sourceType of string to indicate that 
        // conversions from string to integer are supported. (The 
        // GetStandardValues method requires a string to native type 
        // conversion because the items in the drop-down list are 
        // translated to string.)
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
        {
            if( sourceType == typeof(string) )
                return true;
            else 
                return base.CanConvertFrom(context, sourceType);
        }

        // If the type of the value to convert is string, parses the string 
        // and returns the integer to set the value of the property to. 
        // This example first extends the integer array that supplies the 
        // standard values collection if the user-entered value is not 
        // already in the array.
        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if( value.GetType() == typeof(string) )
            {
                // Parses the string to get the integer to set to the property.
                int newVal = int.Parse((string)value);
            
                // Tests whether new integer is already in the list.
                if( !values.Contains(newVal) )
                {
                    // If the integer is not in list, adds it in order.
                    values.Add(newVal);
                    values.Sort();
                }                                
                // Returns the integer value to assign to the property.
                return newVal;
            }
            else
                return base.ConvertFrom(context, culture, value);
        }
    }

    // Provides a test control with an integer property associated with 
    // the StandardValuesIntConverter type converter.
    public class IntStandardValuesControl : System.Windows.Forms.UserControl
    {
        [TypeConverter(typeof(StandardValuesIntConverter))]
        public int TestInt
        {
            get
            {
                return this.integer_field;
            }
            set
            {
                if(value.GetType() == typeof(int))
                    this.integer_field = value;
            }
        }
        private int integer_field = 0;
      
        public IntStandardValuesControl()
        {
            this.BackColor = Color.White;
            this.Size = new Size(472, 80);
        }

        // OnPaint override displays instructions for the example.
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if(this.DesignMode)
            {
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Blue), 5, 5);
                e.Graphics.DrawString("The type converter for the TestInt property of this", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 20);
                e.Graphics.DrawString("component provides a list of standard values to the", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 30);
                e.Graphics.DrawString("Properties window. Setting a value through a property", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 40);
                e.Graphics.DrawString("grid adds it to the list of standard values.", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 50);             
            }
            else
            {
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Blue), 5, 5);         
                e.Graphics.DrawString("This control was intended for use in design mode.", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 20);       
            }
        }
    }
} 
[Visual Basic]
Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Collections
Imports System.Drawing
Imports System.Windows.Forms

Namespace StandardValuesTest

    Public Class StandardValuesIntConverter
        Inherits System.ComponentModel.TypeConverter

        Private values As ArrayList

        Public Sub New()
            ' Initializes the standard values list with defaults.
            values = New ArrayList(New Integer() {1, 2, 3, 4, 5})
        End Sub 'New

        ' Indicates this type converter provides a list of standard values.
        Public Overloads Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
            Return True
        End Function 'GetStandardValuesSupported

        ' Returns a StandardValuesCollection of standard value objects.
        Public Overloads Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
            ' Passes the local integer array.
            Dim svc As New StandardValuesCollection(values)
            Return svc
        End Function 'GetStandardValues

        ' Returns true for a sourceType of string to indicate that 
        ' conversions from string to integer are supported. (The 
        ' GetStandardValues method requires a string to native type 
        ' conversion because the items in the drop-down list are 
        ' translated to string.)
        Public Overloads Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
            If sourceType Is GetType(String) Then
                Return True
            Else
                Return MyBase.CanConvertFrom(context, sourceType)
            End If
        End Function 'CanConvertFrom

        ' If the type of the value to convert is string, parses the string 
        ' and returns the integer to set the value of the property to. 
        ' This example first extends the integer array that supplies the 
        ' standard values collection if the user-entered value is not 
        ' already in the array.
        Public Overloads Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
            If value.GetType() Is GetType(String) Then
                ' Parses the string to get the integer to set to the property.
                Dim newVal As Integer = Integer.Parse(CStr(value))

                ' Tests whether new integer is already in the list.
                If Not values.Contains(newVal) Then
                    ' If the integer is not in list, adds it in order.
                    values.Add(newVal)
                    values.Sort()
                End If
                ' Returns the integer value to assign to the property.
                Return newVal
            Else
                Return MyBase.ConvertFrom(context, culture, value)
            End If
        End Function 'ConvertFrom
    End Class 'StandardValuesIntConverter

    ' Provides a test control with an integer property associated with the 
    ' StandardValuesIntConverter type converter.
    Public Class IntStandardValuesControl
        Inherits System.Windows.Forms.UserControl

        <TypeConverter(GetType(StandardValuesIntConverter))> _
        Public Property TestInt() As Integer
            Get
                Return Me.integer_field
            End Get
            Set(ByVal Value As Integer)
                If Value.GetType() Is GetType(Integer) Then
                    Me.integer_field = Value
                End If
            End Set
        End Property
        Private integer_field As Integer = 0

        Public Sub New()
            Me.BackColor = Color.White
            Me.Size = New Size(472, 80)
        End Sub 'New

        ' OnPaint override displays instructions for the example.
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            If Me.DesignMode Then
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Blue), 5, 5)
                e.Graphics.DrawString("The type converter for the TestInt property of this", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 20)
                e.Graphics.DrawString("component provides a list of standard values to the", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 30)
                e.Graphics.DrawString("Properties window. Setting a value through a property", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 40)
                e.Graphics.DrawString("grid adds it to the list of standard values.", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 50)
            Else
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Blue), 5, 5)
                e.Graphics.DrawString("This control was intended for use in design mode.", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 20)
            End If
        End Sub 'OnPaint
    End Class 'IntStandardValuesControl
End Namespace 'StandardValuesTest

Convertisseurs de type qui génèrent du code pour l'initialisation de propriétés au moment de l'exécution

Le .NET Framework offre la possibilité de générer du code d'initialisation de propriété configurable dynamiquement au moment du design, destiné à initialiser une propriété au moment de l'exécution.

Les développeurs peuvent créer un convertisseur de type qui produit du code d'initialisation basé sur un constructeur. Ces convertisseurs de type peuvent générer du code de constructeur dynamiquement à l'aide de valeurs définies au moment du design afin de configurer les propriétés d'un type au moment de l'exécution. Le convertisseur de type implémente la logique pour configurer le type et les valeurs d'un constructeur pour la propriété.

Si vous devez générer du code en plus d'un constructeur pour initialiser une propriété, il est possible de le faire dynamiquement en implémentant un CodeDomSerializer personnalisé et en appliquant DesignerSerializerAttribute qui associe votre CodeDomSerializer pour un type au type. Cette approche n'est généralement utilisée que pour les scénarios dans lesquels la génération de code personnalisé ou contrôlé dynamiquement pour l'initialisation d'un composant est importante. Pour plus d'informations sur cette approche, consultez la documentation de CodeDomSerializer.

Pour créer un initialiseur de propriété basé sur un constructeur personnalisé, vous devez associer un convertisseur de type au type de la propriété à initialiser ; ce convertisseur de type doit être en mesure de convertir en InstanceDescriptor.

Pour implémenter un convertisseur de type qui produit du code d'initialisation de propriété basé sur un constructeur

  1. Définissez une classe qui dérive de System.ComponentModel.TypeConverter.
  2. Substituez la méthode CanConvertTo. Si le paramètre destinationType est équivalent au type InstanceDescriptor, retournez true.
  3. Substituez la méthode ConvertTo. Si le paramètre destinationType est équivalent au type InstanceDescriptor, construisez et retournez InstanceDescriptor qui représente le constructeur et les arguments du constructeur pour lequel du code doit être généré. Pour créer un InstanceDescriptor qui représente le constructeur et ses paramètres appropriés, procurez-vous ConstructorInfo auprès du Type de la propriété que vous initialisez en appelant la méthode GetConstructor ou GetConstructors avec la signature de méthode appropriée du constructeur que vous recherchez. Créez ensuite un nouveau descripteur d'instance et passez le ConstructorInfo du type qui représente le type de constructeur à utiliser, ainsi qu'un tableau d'objets de paramètre correspondant à la signature du constructeur.

L'exemple suivant implémente un convertisseur de type capable de générer du code d'initialisation de propriétés basées sur un constructeur pour des propriétés de type Point.

public class PointConverter : TypeConverter 
{
   public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
   {
      if (destinationType == typeof(InstanceDescriptor)) 
         return true;
      return base.CanConvertTo(context, destinationType);
   }

public override object ConvertTo(ITypeDescriptorContext context, 
CultureInfo culture, object value, Type destinationType) 
{
      // Insert other ConvertTo operations here.
      //
      if (destinationType == typeof(InstanceDescriptor) && 
value is Point) 
   {
         Point pt = (Point)value;

      ConstructorInfo ctor = typeof(Point).GetConstructor(
new Type[] {typeof(int), typeof(int)});
      if (ctor != null) 
      {
         return new InstanceDescriptor(ctor, new object[] {pt.X, pt.Y});
}
}
   return base.ConvertTo(context, culture, value, destinationType);      
}

Voir aussi

Conversion de type généralisée