Поделиться через


Пошаговое руководство. Создание преобразователя типов для конструктора WPF

Обновлен: Ноябрь 2007

В данном пошаговом руководтсве описано создание преобразователя типов для настраиваемого типа. Windows Presentation Foundation (WPF) для Visual Studio (конструктор) использует преобразователь типов для сериализации настраиваемого типа в язык XAML и из него.

В данном руководстве нужно выполнить следующие задачи:

  • Создание проекта,

  • Создание настраиваемого типа,

  • Создание преобразователя типов,

  • Создание элемента управления, использующего настраиваемый тип,

  • Просмотр настраиваемого типа в окне Свойства.

По окончании вы сможете создавать преобразователи типов для настаиваемых типов.

Bb546926.alert_note(ru-ru,VS.90).gifПримечание.

Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке в зависимости от текущих параметров или версии среды. Чтобы изменить параметры, выберите пункт Параметры импорта и экспорта в меню Сервис. Дополнительные сведения см. в разделе Параметры Visual Studio.

Обязательные компоненты

Для выполнения этой пошаговой инструкции необходимы следующие компоненты:

  • Visual Studio 2008.

Создание проекта

Первым этапом является создание проекта для приложения.

Чтобы создать проект

Создание настраиваемого типа

В этой процедуре создается простой настраиваемый тип с именем Complex, который представляет собой комплексное число. Комплексное число содержит действительную и мнимую части, которые представляются как свойства типа double.

Чтобы создать настраиваемый тип

  1. Добавьте новый класс с именем Complex.vb или Complex.cs в проект TypeConverterExample. Дополнительные сведения см. в разделе Практическое руководство. Добавление в проект новых элементов.

    Файл с кодом для класса Complex откроется в редакторе кода.

  2. Замените определение класса 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 в его строковое представление и обратно. Он также предоставляет список значений по умолчанию, которые могут отображаться в окне конструктора Свойства.

Чтобы создать преобразователь типов

  1. После определения класса 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;
        }
    }
    
  2. В верхней части файла импортируйте пространство имен System.ComponentModel, которое содержит реализацию TypeConverter.

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

Создание элемента управления, использующего настраиваемый тип.

Чтобы просмотреть настраиваемый тип и его преобразователь типа в действии в области конструктора, создайте UserControl со свойством типа Complex.

Чтобы создать элемент управления, использующий настраиваемый тип

  1. Добавьте новый пользовательский элемент управления WPF с именем ComplexNumberControl.xaml в проект TypeConverterExample. Дополнительные сведения см. в разделе Практическое руководство. Добавление новых элементов в проекте WPF.

  2. Просмотрите код для ComplexNumberControl.

  3. Замените определение класса 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()));
    }
    
  4. Выполните построение проекта.

Просмотр настраиваемого типа в окне «Свойства»

Настраиваемый тип можно просмотреть, если ComplexNumberControl размещается в окне WPF.

Чтобы просмотреть настраиваемый тип в окне «Свойства»

  1. Откройте файл Window1.xaml в WPF (конструктор).

  2. В представлении 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>
    
  3. Выберите в режиме конструктора. При необходимости щелкните панель информации вверху для перезагрузки окна.

  4. В представлении XAML выберите элемент ComplexNumberControl.

  5. В окне Свойства выберите свойство ComplexNumber.

    Рядом с элементом ComplexNumber появится стрелка раскрывающегося списка.

  6. Щелкните раскрывающийся список для просмотра списка значений по умолчанию. Выберите значение -1,-1.

    В представлении XAML назначение ComplexNumber изменится на «-1, -1».

См. также

Задачи

Практическое руководство. Реализация преобразователя типов

Ссылки

TypeConverter

TypeConverterAttribute

XamlReader

XamlWriter

System.Windows.Markup

Другие ресурсы

Язык XAML

Расширяемость среды конструктора WPF