Procedura dettagliata: creazione di un convertitore di tipo per WPF Designer
In questa procedura dettagliata viene illustrato come creare un convertitore di tipo per un tipo personalizzato. In WPF Designer per Visual Studio il convertitore di tipo viene utilizzato per serializzare il tipo personalizzato da e verso il linguaggio Extensible Application Markup Language (XAML).
Questa procedura dettagliata prevede l'esecuzione delle 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 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 Gestione delle impostazioni.
Prerequisiti
Per completare la procedura dettagliata, è necessario disporre dei componenti seguenti:
- Visual Studio 2010.
Creazione del progetto
Il primo passaggio consiste nella creazione del progetto per l'applicazione.
Per creare il progetto
In Visual Basic o Visual C# creare un nuovo progetto di applicazione WPF denominato TypeConverterExample. Per ulteriori informazioni, vedere Procedura: creare un nuovo progetto di applicazione WPF.
MainWindow.xaml viene aperto in WPF Designer.
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
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.
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
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; } }
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
Aggiungere un nuovo controllo utente WPF denominato ComplexNumberControl.xaml al progetto TypeConverterExample. Per ulteriori informazioni, vedere Procedura: aggiungere nuovi elementi a un progetto WPF.
Visualizzare il codice per ComplexNumberControl.
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())); }
Compilare 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à
Aprire MainWindow.xaml in WPF Designer.
In visualizzazione XAML sostituire l'elemento Window predefinito con il codice seguente.
<Window x:Class="TypeConverterExample.MainWindow" 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>
Fare clic in visualizzazione Progettazione. Se necessario, fare clic sulla barra informazioni nella parte superiore per ricaricare la finestra.
In visualizzazione XAML fare clic sull'elemento ComplexNumberControl.
Nella finestra Proprietà fare clic sulla proprietà ComplexNumber.
Una freccia a discesa viene visualizzata accanto all'elemento ComplexNumber.
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