方法 : 型コンバーターを実装する

型コンバーターを使用することによって、値のデータ型を変換できます。テキストから値への変換や、値を選択するためのドロップダウン リストが提供されるため、デザイン時のプロパティ構成を簡単に行うことができます。 型コンバーターは、適切に構成されている場合、InstanceDescriptor オブジェクトと System.Reflection オブジェクトを使用してプロパティ構成コードを生成し、実行時にプロパティを初期化するコードの生成に必要な情報を、デザイナーのシリアル化システムに提供します。

値を変換するための型コンバーター

型コンバーターを使用すると、デザイン時と実行時に、文字列から値への変換や、サポートされているデータ型の変換を実行できます。 フォーム デザイナーのプロパティ ブラウザーなどのホストでは、型コンバーターを使用することで、プロパティ値をユーザーに対してテキストとして表示したり、ユーザーが入力したテキストを適切なデータ型の値に変換したりできます。

ほとんどのネイティブ データ型 (Int32String、列挙型など) には既定の型コンバーターがあり、このコンバーターによって文字列から値への変換や検証が実行されます。 既定の型コンバーターは、TypeConverterNameConverter という名前で System.ComponentModel 名前空間に含まれています。 既定の機能では不十分な場合は型コンバーターを拡張できます。また、型コンバーターが関連付けられていないカスタム型を定義した場合は、カスタムの型コンバーターを実装できます。

注意

TypeConverterAttribute 属性は、一般にプロパティやデータ メンバーに適用され、型コンバーターに関連付けられます。 TypeConverterAttribute 属性が型に適用されている場合、その型のプロパティやデータ メンバーにこの属性を再適用する必要はありません。

型コンバーターの実装は、ユーザー インターフェイスの機能には依存しません。 したがって、Windows フォームと Web フォームで同じ型コンバーターを適用できます。

文字列を Point に変換できる単純な型コンバーターを実装するには

  1. TypeConverter から派生するクラスを定義します。

  2. 型コンバーターで変換できる変換元の型を指定する CanConvertFrom メソッドをオーバーライドします。 このメソッドはオーバーロードされます。

  3. 変換を実装する ConvertFrom メソッドをオーバーライドします。 このメソッドはオーバーロードされます。

  4. 型コンバーターで変換できる変換後の型を指定する CanConvertTo メソッドをオーバーライドします。 文字列型に変換する場合は、このメソッドをオーバーライドする必要はありません。 このメソッドはオーバーロードされます。

  5. 変換を実装する ConvertTo メソッドをオーバーライドします。 このメソッドはオーバーロードされます。

  6. 検証を実行する IsValid メソッドをオーバーライドします。 このメソッドはオーバーロードされます。

String 型を Point 型に変換し、Point 型を String 型に変換する型コンバーターを実装するコード例を次に示します。 この例では、CanConvertTo メソッドと IsValid メソッドはオーバーライドされません。

Option Explicit 
Option Strict

Imports System
Imports System.ComponentModel
Imports System.Globalization
Imports System.Drawing

Public Class PointConverter
   Inherits TypeConverter
   
   ' Overrides the CanConvertFrom method of TypeConverter.
   ' The ITypeDescriptorContext interface provides the context for the
   ' conversion. Typically, this interface is used at design time to 
   ' provide information about the design-time container.
   Public Overrides Overloads Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
      If sourceType Is GetType(String) Then
         Return True
      End If
      Return MyBase.CanConvertFrom(context, sourceType)
   End Function
   
   ' Overrides the ConvertFrom method of TypeConverter.
   Public Overrides Overloads Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object
      If TypeOf value Is String Then
         Dim v As String() = CStr(value).Split(New Char() {","c})
         Return New Point(Integer.Parse(v(0)), Integer.Parse(v(1)))
      End If
      Return MyBase.ConvertFrom(context, culture, value)
   End Function
   
   ' Overrides the ConvertTo method of TypeConverter.
   Public Overrides Overloads Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
      If destinationType Is GetType(String) Then
         Return CType(value, Point).X & "," & CType(value, Point).Y
      End If
      Return MyBase.ConvertTo(context, culture, value, destinationType)
   End Function
End Class
using System;
using System.ComponentModel;
using System.Globalization;
using System.Drawing;

public class PointConverter : TypeConverter {
   // Overrides the CanConvertFrom method of TypeConverter.
   // The ITypeDescriptorContext interface provides the context for the
   // conversion. Typically, this interface is used at design time to 
   // provide information about the design-time container.
   public override bool CanConvertFrom(ITypeDescriptorContext context, 
      Type sourceType) {
      
      if (sourceType == typeof(string)) {
         return true;
      }
      return base.CanConvertFrom(context, sourceType);
   }
   // Overrides the ConvertFrom method of TypeConverter.
   public override object ConvertFrom(ITypeDescriptorContext context, 
      CultureInfo culture, object value) {
      if (value is string) {
         string[] v = ((string)value).Split(new char[] {','});
         return new Point(int.Parse(v[0]), int.Parse(v[1]));
      }
      return base.ConvertFrom(context, culture, value);
   }
   // Overrides the ConvertTo method of TypeConverter.
   public override object ConvertTo(ITypeDescriptorContext context, 
      CultureInfo culture, object value, Type destinationType) {  
      if (destinationType == typeof(string)) {
         return ((Point)value).X + "," + ((Point)value).Y;
      }
      return base.ConvertTo(context, culture, value, destinationType);
   }
}

[プロパティ] ウィンドウに標準値のリストを提供する型コンバーター

型コンバーターで、[プロパティ] ウィンドウ コントロールの型に応じた値のリストを提供できます。 型コンバーターが型の標準値のセットを提供する場合、[プロパティ] ウィンドウ コントロール内の関連付けられた型のプロパティの値入力フィールドには、クリックしたときにプロパティの値として設定するための値の一覧を表示する下向きの矢印が表示されます。

この型コンバーターが関連付けられている型のプロパティをデザイン時環境のプロパティ ブラウザーで選択した場合、値入力フィールドにはボタンが表示されます。このボタンは、プロパティの型の標準値をドロップダウン リストで表示し、値を選択できるようにします。

プロパティ ブラウザーで標準値のドロップダウン リストを提供する単純な型コンバーターを実装するには

  1. TypeConverter から派生するクラスを定義します。

  2. GetStandardValuesSupported メソッドをオーバーライドし、true を返します。

  3. GetStandardValues メソッドをオーバーライドし、プロパティの型の標準値を含む TypeConverter.StandardValuesCollection を返します。 プロパティの標準値は、プロパティと同じ型にする必要があります。

  4. CanConvertFrom メソッドをオーバーライドし、sourceType パラメーター値が文字列型の場合は true を返します。

  5. ConvertFrom メソッドをオーバーライドし、value パラメーターに基づいてプロパティの適切な値を返します。

  6. 型コンバーターの型を示す TypeConverterAttribute を、標準値のセットを提供する型に適用します。

型コンバーターが関連付けられている型のプロパティの [プロパティ] ウィンドウに、標準値のリストを提供する型コンバーターの例を次に示します。 この例の型コンバーターは、関連付けられている整数型のプロパティをサポートします。 Visual Studio でこの例を使用するには、コードをコンパイルしてクラス ライブラリを作成し、IntStandardValuesControl コンポーネントをツールボックスに追加します。 デザイン モードのフォームに IntStandardValuesControl のインスタンスを追加し、このコントロールを選択した状態で、[プロパティ] ウィンドウをスクロールして TestInt プロパティを表示します。 このプロパティの値入力フィールドを選択すると、下向きの矢印が表示され、クリックすると標準値のドロップダウン リストが表示されます。 整数値を入力すると、その値が標準値のリストに追加され、プロパティは指定した値に設定されます。

using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;

namespace StandardValuesTest
{  
    public class StandardValuesIntConverter : System.ComponentModel.TypeConverter
    {
        private ArrayList values;
        public StandardValuesIntConverter()
        {
            // Initializes the standard values list with defaults.
            values = new ArrayList(new int[] { 1, 2, 3, 4, 5 });
        }

        // Indicates this converter provides a list of standard values.
        public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context)
        {
            return true;
        }

        // Returns a StandardValuesCollection of standard value objects.
        public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context)
        {        
            // Passes the local integer array.
            StandardValuesCollection svc = 
                new StandardValuesCollection(values);       
            return svc;
        }

        // Returns true for a sourceType of string to indicate that 
        // conversions from string to integer are supported. (The 
        // GetStandardValues method requires a string to native type 
        // conversion because the items in the drop-down list are 
        // translated to string.)
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
        {
            if( sourceType == typeof(string) )
                return true;
            else 
                return base.CanConvertFrom(context, sourceType);
        }

        // If the type of the value to convert is string, parses the string 
        // and returns the integer to set the value of the property to. 
        // This example first extends the integer array that supplies the 
        // standard values collection if the user-entered value is not 
        // already in the array.
        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if( value.GetType() == typeof(string) )
            {
                // Parses the string to get the integer to set to the property.
                int newVal = int.Parse((string)value);
            
                // Tests whether new integer is already in the list.
                if( !values.Contains(newVal) )
                {
                    // If the integer is not in list, adds it in order.
                    values.Add(newVal);
                    values.Sort();
                }                                
                // Returns the integer value to assign to the property.
                return newVal;
            }
            else
                return base.ConvertFrom(context, culture, value);
        }
    }

    // Provides a test control with an integer property associated with 
    // the StandardValuesIntConverter type converter.
    public class IntStandardValuesControl : System.Windows.Forms.UserControl
    {
        [TypeConverter(typeof(StandardValuesIntConverter))]
        public int TestInt
        {
            get
            {
                return this.integer_field;
            }
            set
            {
                if(value.GetType() == typeof(int))
                    this.integer_field = value;
            }
        }
        private int integer_field = 0;
      
        public IntStandardValuesControl()
        {
            this.BackColor = Color.White;
            this.Size = new Size(472, 80);
        }

        // OnPaint override displays instructions for the example.
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if(this.DesignMode)
            {
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Blue), 5, 5);
                e.Graphics.DrawString("The type converter for the TestInt property of this", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 20);
                e.Graphics.DrawString("component provides a list of standard values to the", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 30);
                e.Graphics.DrawString("Properties window. Setting a value through a property", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 40);
                e.Graphics.DrawString("grid adds it to the list of standard values.", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 50);             
            }
            else
            {
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Blue), 5, 5);         
                e.Graphics.DrawString("This control was intended for use in design mode.", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 20);       
            }
        }
    }
}
Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Collections
Imports System.Drawing
Imports System.Windows.Forms

Namespace StandardValuesTest

    Public Class StandardValuesIntConverter
        Inherits System.ComponentModel.TypeConverter

        Private values As ArrayList

        Public Sub New()
            ' Initializes the standard values list with defaults.
            values = New ArrayList(New Integer() {1, 2, 3, 4, 5})
        End Sub 'New

        ' Indicates this type converter provides a list of standard values.
        Public Overloads Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
            Return True
        End Function 'GetStandardValuesSupported

        ' Returns a StandardValuesCollection of standard value objects.
        Public Overloads Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
            ' Passes the local integer array.
            Dim svc As New StandardValuesCollection(values)
            Return svc
        End Function 'GetStandardValues

        ' Returns true for a sourceType of string to indicate that 
        ' conversions from string to integer are supported. (The 
        ' GetStandardValues method requires a string to native type 
        ' conversion because the items in the drop-down list are 
        ' translated to string.)
        Public Overloads Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
            If sourceType Is GetType(String) Then
                Return True
            Else
                Return MyBase.CanConvertFrom(context, sourceType)
            End If
        End Function 'CanConvertFrom

        ' If the type of the value to convert is string, parses the string 
        ' and returns the integer to set the value of the property to. 
        ' This example first extends the integer array that supplies the 
        ' standard values collection if the user-entered value is not 
        ' already in the array.
        Public Overloads Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
            If value.GetType() Is GetType(String) Then
                ' Parses the string to get the integer to set to the property.
                Dim newVal As Integer = Integer.Parse(CStr(value))

                ' Tests whether new integer is already in the list.
                If Not values.Contains(newVal) Then
                    ' If the integer is not in list, adds it in order.
                    values.Add(newVal)
                    values.Sort()
                End If
                ' Returns the integer value to assign to the property.
                Return newVal
            Else
                Return MyBase.ConvertFrom(context, culture, value)
            End If
        End Function 'ConvertFrom
    End Class 'StandardValuesIntConverter

    ' Provides a test control with an integer property associated with the 
    ' StandardValuesIntConverter type converter.
    Public Class IntStandardValuesControl
        Inherits System.Windows.Forms.UserControl

        <TypeConverter(GetType(StandardValuesIntConverter))> _
        Public Property TestInt() As Integer
            Get
                Return Me.integer_field
            End Get
            Set(ByVal Value As Integer)
                If Value.GetType() Is GetType(Integer) Then
                    Me.integer_field = Value
                End If
            End Set
        End Property
        Private integer_field As Integer = 0

        Public Sub New()
            Me.BackColor = Color.White
            Me.Size = New Size(472, 80)
        End Sub 'New

        ' OnPaint override displays instructions for the example.
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            If Me.DesignMode Then
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Blue), 5, 5)
                e.Graphics.DrawString("The type converter for the TestInt property of this", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 20)
                e.Graphics.DrawString("component provides a list of standard values to the", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 30)
                e.Graphics.DrawString("Properties window. Setting a value through a property", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 40)
                e.Graphics.DrawString("grid adds it to the list of standard values.", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 50)
            Else
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Blue), 5, 5)
                e.Graphics.DrawString("This control was intended for use in design mode.", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 20)
            End If
        End Sub 'OnPaint
    End Class 'IntStandardValuesControl
End Namespace 'StandardValuesTest

実行時にプロパティを初期化するコードを生成する型コンバーター

.NET Framework には、実行時にプロパティを初期化するための、動的なプロパティ初期化コードをデザイン時に生成する機能が用意されています。

開発者は、コンストラクター ベースの初期化コードを生成する型コンバーターを作成できます。 このような型コンバーターでは、実行時に型のプロパティを構成するために、デザイン時に設定された値を使用して動的にコンストラクター コードを生成できます。 型コンバーターは、プロパティのコンストラクターの型と値を構成するロジックを実装します。

コンストラクター以外で、プロパティを初期化するコードを生成する必要がある場合は、カスタムの CodeDomSerializer を実装し、その CodeDomSerializer を特定の型に関連付ける DesignerSerializerAttribute を適用することによって、動的にコードを生成できます。 この方法は、通常、コンポーネントを初期化するためのコードの生成を動的に制御またはカスタマイズする必要がある場合にだけ使用されます。 この方法の詳細については、CodeDomSerializer の説明を参照してください。

カスタム コンストラクター ベースのプロパティ初期化子を構築するには、型コンバーターを、初期化するプロパティの型に関連付ける必要があり、型コンバーターは InstanceDescriptor に変換できる必要があります。

コンストラクター ベースのプロパティ初期化コードを生成する型コンバーターを実装するには

  1. TypeConverter から派生するクラスを定義します。

  2. CanConvertTo メソッドをオーバーライドします。 destinationType パラメーターが InstanceDescriptor 型である場合は、true を返します。

  3. ConvertTo メソッドをオーバーライドします。 destinationType パラメーターが InstanceDescriptor 型である場合は、コードを生成するコンストラクターとコンストラクターの引数を表す InstanceDescriptor を構築し、返します。 適切なコンストラクターとパラメーターを表す InstanceDescriptor を作成するには、目的のコンストラクターの該当するメソッド シグネチャを使用して GetConstructor メソッドまたは GetConstructors メソッドを呼び出し、初期化するプロパティの Type から ConstructorInfo を取得します。 次に、新しいインスタンス記述子を作成し、使用するコンストラクターの型を表す ConstructorInfo と、コンストラクターのシグネチャに一致するパラメーター オブジェクトの配列を渡します。

Point 型のプロパティに対するコンストラクター ベースのプロパティ初期化コードを生成できる型コンバーターを実装する例を次に示します。

public class PointConverter : TypeConverter 
{
   public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
   {
      if (destinationType == typeof(InstanceDescriptor)) 
         return true;
      return base.CanConvertTo(context, destinationType);
   }

public override object ConvertTo(ITypeDescriptorContext context, 
CultureInfo culture, object value, Type destinationType) 
{
      // Insert other ConvertTo operations here.
      //
      if (destinationType == typeof(InstanceDescriptor) && 
value is Point) 
   {
         Point pt = (Point)value;

      ConstructorInfo ctor = typeof(Point).GetConstructor(
new Type[] {typeof(int), typeof(int)});
      if (ctor != null) 
      {
         return new InstanceDescriptor(ctor, new object[] {pt.X, pt.Y});
}
}
   return base.ConvertTo(context, culture, value, destinationType);      
}

コードのコンパイル

  • カスタムの TypeConverter を開発する場合は、ビルド番号をビルドごとにインクリメントすることをお勧めします。 これによって、TypeConverter のキャッシュされた古いバージョンがデザイン環境に作成されることを防止できます。

参照

概念

一般的な型変換