Partager via


Procédure pas à pas : création d'un convertisseur de type pour le concepteur WPF

Mise à jour : novembre 2007

Cette procédure pas à pas indique comment créer un convertisseur de type pour un type personnalisé. Le Concepteur Windows Presentation Foundation (WPF) pour Visual Studio utilise le convertisseur de type pour sérialiser votre type personnalisé avec le langage XAML (Extensible Application Markup Language).

Dans cette procédure pas à pas, vous exécutez les tâches suivantes :

  • créer le projet ;

  • créer le type personnalisé ;

  • créer le convertisseur de type ;

  • créer un contrôle qui utilise le type personnalisé ;

  • consulter le type personnalisé dans la fenêtre Propriétés.

Lorsque vous avez terminé, vous pouvez créer des convertisseurs de type pour vos types personnalisés.

Remarque :

Selon vos paramètres actifs ou votre édition, les boîtes de dialogue et les commandes de menu auxquelles vous accédez peuvent différer de celles qui sont décrites dans l'aide. Pour modifier vos paramètres, choisissez Importation et exportation de paramètres dans le menu Outils. Pour plus d'informations, consultez Paramètres Visual Studio.

Composants requis

Vous avez besoin des composants suivants pour accomplir cette procédure pas à pas :

  • Visual Studio 2008.

Création du projet

La première étape consiste à créer le projet pour l'application.

Pour créer le projet

  • Créez un projet d'application WPF dans Visual Basic ou Visual C# nommé TypeConverterExample. Pour plus d'informations, consultez Comment : créer un projet d'application WPF.

    Window1.xaml s'ouvre dans le Concepteur WPF.

Création du type personnalisé

Dans cette procédure, vous créez un type personnalisé simple nommé Complex, qui représente un nombre complexe. Un nombre complexe contient une partie réelle et une partie imaginaire ; ces parties sont exposées en tant que propriétés double.

Pour créer un type personnalisé

  1. Ajoutez une nouvelle classe nommée Complex.vb ou Complex.cs au projet TypeConverterExample. Pour plus d'informations, consultez Comment : ajouter de nouveaux éléments de projet.

    Le fichier de code de la classe Complex s'ouvre dans l'éditeur de code.

  2. Remplacez la définition de la classe Complex par le code suivant.

    <TypeConverter(GetType(ComplexTypeConverter))> _
    Public Class Complex
        Private realValue As Double
        Private imaginaryValue As Double
    
        Public Sub New()
    
        End Sub
    
        Public Sub New(ByVal real As Double, ByVal imaginary As Double)
            Me.realValue = real
            Me.imaginaryValue = imaginary
    
        End Sub
    
        Public Property Real() As Double
            Get
                Return realValue
            End Get
    
            Set(ByVal value As Double)
                realValue = value
            End Set
        End Property
    
        Public Property Imaginary() As Double
            Get
                Return imaginaryValue
            End Get
    
            Set(ByVal value As Double)
                imaginaryValue = value
            End Set
        End Property
    
        Public Overrides Function ToString() As String
            Return String.Format( _
                CultureInfo.CurrentCulture, _
                "{0}{2}{1}", _
                Me.realValue, _
                Me.imaginaryValue, _
                CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator)
        End Function
    
        Public Shared Function Parse(ByVal complexNumber As String) As Complex
            If String.IsNullOrEmpty(complexNumber) Then
                Return New Complex()
            End If
    
            'The parts array holds the real and imaginary parts of the object.
            Dim separator() As Char = {","}
            Dim parts() As String = complexNumber.Split(separator)
    
            If (parts.Length <> 2) Then
                Throw New FormatException( _
                    String.Format( _
                        "Cannot parse '{0}' into a Complex object because " & _
                        "it is not in the '<real>, <imaginary>' format.", _
                    complexNumber))
            End If
    
            Return New Complex( _
                Double.Parse(parts(0).Trim()), _
                Double.Parse(parts(1).Trim()))
    
        End Function
    
    End Class
    
    [TypeConverter( typeof( ComplexTypeConverter ) )]
    public class Complex
    {
        private double realValue;
        private double imaginaryValue;
    
        public Complex()
        {
        }
    
        public Complex(double real, double imaginary)
        {
            this.realValue = real;
            this.imaginaryValue = imaginary;
        }
    
        public double Real
        {
            get
            {
                return realValue;
            }
    
            set
            {
                realValue = value;
            }
        }
    
        public double Imaginary
        {
            get 
            {
                return imaginaryValue; 
            }
    
            set 
            {
                imaginaryValue = value; 
            }
        }
    
        public override string ToString()
        {
            return String.Format(
                CultureInfo.CurrentCulture, 
                "{0}{2}{1}", 
                this.realValue, 
                this.imaginaryValue,
                CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator);
        }
    
        public static Complex Parse(string complexNumber)
        {
            if (String.IsNullOrEmpty(complexNumber))
            {
                return new Complex();
            }
    
            // The parts array holds the real and 
            // imaginary parts of the object.
            string[] parts = complexNumber.Split(',');       
    
            if (2 != parts.Length)
            {
                throw new FormatException(
                    String.Format(
                    "Cannot parse '{0}' into a Complex object because " +
                    "it is not in the \"<real>, <imaginary>\" format.",
                    complexNumber));
            }
    
            return new Complex(double.Parse(parts[0].Trim()), double.Parse(parts[1].Trim()));
    
        }
    }
    

Création du convertisseur de type

Vous définissez à présent le convertisseur de type pour la classe Complex. La classe ComplexTypeConverter convertit un objet Complex en sa représentation sous forme de chaîne et inversement. Elle fournit également la liste des valeurs par défaut, qui peuvent s'afficher dans la fenêtre Propriétés d'un concepteur.

Pour créer le convertisseur de type

  1. Après la définition de la classe Complex, insérez le code suivant pour la classe ComplexTypeConverter:

    Public Class ComplexTypeConverter
        Inherits TypeConverter
    
        Private Shared defaultValues As List(Of Complex) = New List(Of Complex)()
    
        Shared Sub New()
            defaultValues.Add(New Complex(0, 0))
            defaultValues.Add(New Complex(1, 1))
            defaultValues.Add(New Complex(-1, 1))
            defaultValues.Add(New Complex(-1, -1))
            defaultValues.Add(New Complex(1, -1))
        End Sub
    
        ' Override CanConvertFrom to return true for String-to-Complex conversions.
        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
    
        ' Override CanConvertTo to return true for Complex-to-String conversions.
        Public Overrides Function CanConvertTo( _
            ByVal context As System.ComponentModel.ITypeDescriptorContext, _
            ByVal destinationType As System.Type) As Boolean
    
            If destinationType Is GetType(String) Then
                Return True
            End If
    
            Return MyBase.CanConvertTo(context, destinationType)
    
        End Function
    
        ' Override ConvertFrom to convert from a string to an instance of Complex.
        Public Overrides Function ConvertFrom( _
            ByVal context As ITypeDescriptorContext, _
            ByVal culture As System.Globalization.CultureInfo, _
            ByVal value As Object) As Object
    
            If TypeOf value Is String Then
                Try
                    Return Complex.Parse(CType(value, String))
                Catch ex As Exception
                    Throw New Exception( _
                        String.Format( _
                            "Cannot convert '{0}' ({1}) because {2}", _
                            value, _
                            value.GetType(), _
                            ex.Message), ex)
    
                End Try
            End If
    
            Return MyBase.ConvertFrom(context, culture, value)
    
        End Function
    
        ' Override ConvertTo to convert from an instance of Complex to string.
        Public Overrides Function ConvertTo( _
            ByVal context As ITypeDescriptorContext, _
            ByVal culture As System.Globalization.CultureInfo, _
            ByVal value As Object, _
            ByVal destinationType As Type) As Object
    
            If destinationType Is Nothing Then
                Throw New ArgumentNullException("destinationType")
            End If
    
            Dim c As Complex = CType(value, Complex)
    
            If (c IsNot Nothing) Then
                If Me.CanConvertTo(context, destinationType) Then
                    Return c.ToString()
                End If
            End If
    
            Return MyBase.ConvertTo(context, culture, value, destinationType)
    
        End Function
    
    
        Public Overrides Function GetStandardValuesSupported( _
            ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
    
            Return True
    
        End Function
    
    
        Public Overrides Function GetStandardValues( _
            ByVal context As System.ComponentModel.ITypeDescriptorContext) _
                As TypeConverter.StandardValuesCollection
    
            Dim svc As New StandardValuesCollection(defaultValues)
            Return svc
    
        End Function
    End Class
    
    public class ComplexTypeConverter : TypeConverter
    {
        private static List<Complex> defaultValues = new List<Complex>();
    
        static ComplexTypeConverter()
        {
            defaultValues.Add(new Complex(0, 0));
            defaultValues.Add(new Complex( 1, 1));
            defaultValues.Add(new Complex(-1, 1));
            defaultValues.Add(new Complex(-1,-1));
            defaultValues.Add(new Complex( 1,-1));
        }
    
        // Override CanConvertFrom to return true for String-to-Complex conversions.
        public override bool CanConvertFrom(
            ITypeDescriptorContext context, 
            Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
    
            return base.CanConvertFrom(context, sourceType);
        }
    
        // Override CanConvertTo to return true for Complex-to-String conversions.
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }
    
            return base.CanConvertTo(context, destinationType);
        }
    
        // Override ConvertFrom to convert from a string to an instance of Complex.
        public override object ConvertFrom(
            ITypeDescriptorContext context, 
            System.Globalization.CultureInfo culture, 
            object value)
        {
            string text = value as string;
    
            if (text != null)
            {
                try
                {
                    return Complex.Parse(text);
                }
                catch (Exception e)
                {
                    throw new Exception(
                        String.Format("Cannot convert '{0}' ({1}) because {2}", 
                                        value, 
                                        value.GetType(), 
                                        e.Message), e);
                }
            }
    
            return base.ConvertFrom(context, culture, value);
        }
    
        // Override ConvertTo to convert from an instance of Complex to string.
        public override object ConvertTo(
            ITypeDescriptorContext context, 
            System.Globalization.CultureInfo culture, 
            object value, 
            Type destinationType)
        {
            if (destinationType == null)
            {
                throw new ArgumentNullException("destinationType");
            }
    
            //Convert Complex to a string in a standard format.
            Complex c = value as Complex;
    
            if (c != null && this.CanConvertTo(context, destinationType))
            {
                return c.ToString();
            }
    
            return base.ConvertTo(context, culture, value, destinationType);
        }
    
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
    
        public override TypeConverter.StandardValuesCollection GetStandardValues(
            ITypeDescriptorContext context)
        {   
            StandardValuesCollection svc = new StandardValuesCollection(defaultValues);       
            return svc;
        }
    }
    
  2. Au début du fichier, importez l'espace de noms System.ComponentModel, qui contient l'implémentation TypeConverter.

    Imports System.ComponentModel
    Imports System.Globalization
    
    using System.ComponentModel;
    using System.Globalization;
    

Création d'un contrôle qui utilise le type personnalisé

Pour afficher votre type personnalisé et son convertisseur de type en action sur l'aire de conception, vous créez un UserControl avec une propriété du type Complex.

Pour créer un contrôle qui utilise le type personnalisé

  1. Ajoutez un nouveau contrôle utilisateur WPF nommé ComplexNumberControl.xaml au projet TypeConverterExample. Pour plus d'informations, consultez Comment : ajouter de nouveaux éléments à un projet WPF.

  2. Affichez le code de ComplexNumberControl.

  3. Remplacez la définition de la classe ComplexNumberControl par le code suivant.

    Partial Public Class ComplexNumberControl
        Inherits System.Windows.Controls.UserControl
    
        Private complexNumberValue As Complex
    
        Public Sub New()
            InitializeComponent()
    
        End Sub
    
        Public Property ComplexNumber() As Complex
            Get
                Return Me.GetValue(ComplexNumberProperty)
            End Get
    
            Set(ByVal value As Complex)
                Me.SetValue(ComplexNumberProperty, value)
            End Set
        End Property
    
        Public Shared ReadOnly ComplexNumberProperty As DependencyProperty = DependencyProperty.Register( _
          "ComplexNumber", _
          GetType(Complex), _
          GetType(ComplexNumberControl), _
          New PropertyMetadata(New Complex()))
    
    End Class
    
    public partial class ComplexNumberControl : UserControl
    {
        public ComplexNumberControl()
        {
            InitializeComponent();
        }
    
        public Complex ComplexNumber
        {
            get 
            { 
                return (Complex)this.GetValue(ComplexNumberProperty); 
            }
    
            set 
            { 
                this.SetValue(ComplexNumberProperty, value); 
            }
        }
        public static readonly DependencyProperty ComplexNumberProperty = DependencyProperty.Register(
          "ComplexNumber",
          typeof(Complex),
          typeof(ComplexNumberControl),
          new PropertyMetadata(new Complex()));
    }
    
  4. Générez le projet.

Affichage du type personnalisé dans la fenêtre Propriétés

Vous pouvez consulter votre type personnalisé lorsque ComplexNumberControl est hébergé dans une fenêtre WPF.

Pour afficher le type personnalisé dans la fenêtre Propriétés

  1. Ouvrez Window1.xaml dans le Concepteur WPF.

  2. En mode XAML, remplacez l'élément Window par le code suivant.

    <Window x:Class="TypeConverterExample.Window1"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:TypeConverterExample"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <c:ComplexNumberControl ComplexNumber="0,0" />
        </Grid>
    </Window>
    
    <Window x:Class="TypeConverterExample.Window1"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:TypeConverterExample"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <c:ComplexNumberControl ComplexNumber="0,0" />
        </Grid>
    </Window>
    
  3. Activez le mode Design. Si nécessaire, cliquez sur la barre Informations située dans la partie supérieure pour recharger la fenêtre.

  4. En mode XAML, cliquez sur l'élément ComplexNumberControl.

  5. Dans la fenêtre Propriétés, cliquez sur la propriété ComplexNumber.

    Une flèche de déroulement apparaît en regard de l'élément ComplexNumber.

  6. Cliquez sur la flèche déroulante pour afficher la liste des valeurs par défaut. Sélectionnez la valeur -1,-1.

    En mode XAML, l'assignation ComplexNumber est remplacée par "-1,-1."

Voir aussi

Tâches

Comment : implémenter un convertisseur de type

Référence

TypeConverter

TypeConverterAttribute

XamlReader

XamlWriter

System.Windows.Markup

Autres ressources

XAML

Extensibilité du concepteur WPF