Condividi tramite


Procedura dettagliata: creazione di un convertitore di tipi per Progettazione WPF

Aggiornamento: novembre 2007

In questa procedura dettagliata viene illustrato come creare un convertitore di tipo per un tipo personalizzato. In Progettazione Windows Presentation Foundation (WPF) per Visual Studio il convertitore di tipo viene utilizzato per serializzare il tipo personalizzato da e verso il linguaggio Extensible Application Markup Language (XAML).

In questa procedura dettagliata vengono eseguite le attività seguenti:

  • Creare il progetto.

  • Creare il tipo personalizzato.

  • Creare il convertitore di tipo.

  • Creare un controllo che utilizza il tipo personalizzato.

  • Visualizzare il tipo personalizzato nella finestra Proprietà.

Al termine, sarà possibile creare convertitori di tipo per i tipi personalizzati.

Nota:

È possibile che le finestre di dialogo e i comandi di menu visualizzati siano diversi da quelli descritti nella Guida in linea, a seconda delle impostazioni attive o dell'edizione del programma. Per modificare le impostazioni, scegliere Importa/esporta impostazioni dal menu Strumenti. Per ulteriori informazioni, vedere Impostazioni di Visual Studio.

Prerequisiti

Per completare questa procedura dettagliata, è necessario disporre dei seguenti componenti:

  • Visual Studio 2008.

Creazione del progetto

Il primo passaggio consiste nella creazione del progetto per l'applicazione.

Per creare il progetto

Creazione del tipo personalizzato

In questa procedura, viene creato un semplice tipo personalizzato denominato Complex che rappresenta un numero complesso. Un numero complesso ha una parte reale e una parte immaginaria e queste parti sono esposte come proprietà double.

Per creare un tipo personalizzato

  1. Aggiungere una nuova classe denominata Complex.vb o Complex.cs al progetto TypeConverterExample. Per ulteriori informazioni, vedere Procedura: aggiungere elementi di progetto nuovi.

    Il file di codice per la classe Complex viene aperto nell'editor del codice.

  2. Sostituire la definizione della classe Complex con il codice seguente.

    <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()));
    
        }
    }
    

Creazione del convertitore di tipo

A questo punto viene definito il convertitore di tipo per la classe Complex. La classe ComplexTypeConverter converte un oggetto Complex nella relativa rappresentazione in stringa e viceversa. Fornisce inoltre un elenco di valori predefiniti che possono essere visualizzati nella finestra Proprietà di una finestra di progettazione.

Per creare il convertitore di tipo

  1. Dopo la definizione della classe Complex inserire il seguente codice per 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. All'inizio del file, importare lo spazio dei nomi System.ComponentModel che contiene l'implementazione di TypeConverter.

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

Creazione di un controllo che utilizza il tipo personalizzato

Per vedere il tipo personalizzato e il relativo convertitore di tipo in azione nell'area di progettazione, creare un UserControl con una proprietà di tipo Complex.

Per creare un controllo che utilizza il tipo personalizzato

  1. Aggiungere un nuovo controllo utente WPF denominato ComplexNumberControl.xaml al progetto TypeConverterExample. Per ulteriori informazioni, vedere Procedura: aggiungere nuovi elementi a un progetto WPF.

  2. Visualizzare il codice per ComplexNumberControl.

  3. Sostituire la definizione della classe ComplexNumberControl con il codice seguente.

    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. Generare il progetto.

Visualizzazione del tipo personalizzato nella finestra Proprietà

È possibile visualizzare il tipo personalizzato quando ComplexNumberControl è ospitato in una finestra WPF.

Per visualizzare il tipo personalizzato nella finestra Proprietà

  1. Aprire Window1.xaml in WPF Designer.

  2. In visualizzazione XAML sostituire l'elemento Window predefinito con il codice seguente.

    <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. Fare clic in visualizzazione Progettazione. Se necessario, fare clic sulla barra informazioni nella parte superiore per ricaricare la finestra.

  4. In visualizzazione XAML fare clic sull'elemento ComplexNumberControl.

  5. Nella finestra Proprietà fare clic sulla proprietà ComplexNumber.

    Una freccia a discesa viene visualizzata accanto all'elemento ComplexNumber.

  6. Fare clic sull'elenco a discesa per vedere l'elenco di valori predefiniti. Selezionare il valore -1, -1.

    In visualizzazione XAML l'assegnazione di ComplexNumber viene modificata in "-1,-1".

Vedere anche

Attività

Procedura: implementare un convertitore di tipi

Riferimenti

TypeConverter

TypeConverterAttribute

XamlReader

XamlWriter

System.Windows.Markup

Altre risorse

XAML

Estensibilità di Progettazione WPF