Пошаговое руководство. Создание преобразователя типов для конструктора WPF
Обновлен: Ноябрь 2007
В данном пошаговом руководтсве описано создание преобразователя типов для настраиваемого типа. Windows Presentation Foundation (WPF) для Visual Studio (конструктор) использует преобразователь типов для сериализации настраиваемого типа в язык XAML и из него.
В данном руководстве нужно выполнить следующие задачи:
Создание проекта,
Создание настраиваемого типа,
Создание преобразователя типов,
Создание элемента управления, использующего настраиваемый тип,
Просмотр настраиваемого типа в окне Свойства.
По окончании вы сможете создавать преобразователи типов для настаиваемых типов.
![]() |
---|
Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке в зависимости от текущих параметров или версии среды. Чтобы изменить параметры, выберите пункт Параметры импорта и экспорта в меню Сервис. Дополнительные сведения см. в разделе Параметры Visual Studio. |
Обязательные компоненты
Для выполнения этой пошаговой инструкции необходимы следующие компоненты:
- Visual Studio 2008.
Создание проекта
Первым этапом является создание проекта для приложения.
Чтобы создать проект
Создайте новый проект приложения WPF в Visual Basic или Visual C# с именем TypeConverterExample. Дополнительные сведения см. в разделе Практическое руководство. Создание нового проекта приложения WPF.
Файл Window1.xaml откроется в конструкторе WPF (конструктор).
Создание настраиваемого типа
В этой процедуре создается простой настраиваемый тип с именем Complex, который представляет собой комплексное число. Комплексное число содержит действительную и мнимую части, которые представляются как свойства типа double.
Чтобы создать настраиваемый тип
Добавьте новый класс с именем Complex.vb или Complex.cs в проект TypeConverterExample. Дополнительные сведения см. в разделе Практическое руководство. Добавление в проект новых элементов.
Файл с кодом для класса Complex откроется в редакторе кода.
Замените определение класса Complex на следующий код.
<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())); } }
Создание преобразователя типов
Теперь можно определить преобразователь типа для класса Complex. Класс ComplexTypeConverter преобразует объект Complex в его строковое представление и обратно. Он также предоставляет список значений по умолчанию, которые могут отображаться в окне конструктора Свойства.
Чтобы создать преобразователь типов
После определения класса Complex вставьте следующий код для класса 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; } }
В верхней части файла импортируйте пространство имен System.ComponentModel, которое содержит реализацию TypeConverter.
Imports System.ComponentModel Imports System.Globalization
using System.ComponentModel; using System.Globalization;
Создание элемента управления, использующего настраиваемый тип.
Чтобы просмотреть настраиваемый тип и его преобразователь типа в действии в области конструктора, создайте UserControl со свойством типа Complex.
Чтобы создать элемент управления, использующий настраиваемый тип
Добавьте новый пользовательский элемент управления WPF с именем ComplexNumberControl.xaml в проект TypeConverterExample. Дополнительные сведения см. в разделе Практическое руководство. Добавление новых элементов в проекте WPF.
Просмотрите код для ComplexNumberControl.
Замените определение класса ComplexNumberControl на следующий код.
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())); }
Выполните построение проекта.
Просмотр настраиваемого типа в окне «Свойства»
Настраиваемый тип можно просмотреть, если ComplexNumberControl размещается в окне WPF.
Чтобы просмотреть настраиваемый тип в окне «Свойства»
Откройте файл Window1.xaml в WPF (конструктор).
В представлении XAML замените элемент 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>
<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>
Выберите в режиме конструктора. При необходимости щелкните панель информации вверху для перезагрузки окна.
В представлении XAML выберите элемент ComplexNumberControl.
В окне Свойства выберите свойство ComplexNumber.
Рядом с элементом ComplexNumber появится стрелка раскрывающегося списка.
Щелкните раскрывающийся список для просмотра списка значений по умолчанию. Выберите значение -1,-1.
В представлении XAML назначение ComplexNumber изменится на «-1, -1».
См. также
Задачи
Практическое руководство. Реализация преобразователя типов