none
Type型のプロパティをプロパティウィンドウで設定したい RRS feed

  • 質問

  • Type型のプロパティを持ったカスタムコントロールを作成し、フォームに貼り付けたのですが
    プロパティウィンドウではグレー表示されて編集することができません。
    調べてみて、TypeConverter属性を指定してやれば編集できそうだということまでは
    つかんだのですが、グレー表示は解消されて黒表示にはなったものの、依然Type型を
    編集することができません。

    希望としては、プロパティウィンドウに例えば、
    String と指定すれば GetType(String) がプロパティに指定され、
    Integer と指定すれば GetType(Integer) がプロパティに指定されるようなものを期待しています。
    こういうことはできないのでしょうか?

    2006年11月6日 0:52

すべての返信

  •  コリン星人 さんからの引用

    Type型のプロパティを持ったカスタムコントロールを作成し、フォームに貼り付けたのですが
    プロパティウィンドウではグレー表示されて編集することができません。
    調べてみて、TypeConverter属性を指定してやれば編集できそうだということまでは
    つかんだのですが、グレー表示は解消されて黒表示にはなったものの、依然Type型を
    編集することができません。

    希望としては、プロパティウィンドウに例えば、
    String と指定すれば GetType(String) がプロパティに指定され、
    Integer と指定すれば GetType(Integer) がプロパティに指定されるようなものを期待しています。
    こういうことはできないのでしょうか?

      Public Property Val() As TypeCode

     こんな感じで TypeCodeにすると ある程度の型を指定できますよ。(integerやstring程度なら)

     

    2006年11月6日 3:47
  •  かずboo さんからの引用

    Public Property Val() As TypeCode
    こんな感じで TypeCodeにすると ある程度の型を指定できますよ。(integerやstring程度なら)

    フォローありがとうございます。
    型の種類はこれで十分なのですが、内部的には処理の途中でもいいのでTypeオブジェクトが欲しいのですが、
    TypeCodeからTypeを取得する方法が見つかりません。
    Type.GetType(TypeCode.String.ToString()) では残念ながら無理でした。
    TypeCodeからTypeオブジェクトを取得する方法は何かありますか?

    2006年11月6日 6:10
  •  コリン星人 さんからの引用

    TypeCodeからTypeを取得する方法が見つかりません。
    Type.GetType(TypeCode.String.ToString()) では残念ながら無理でした。
    TypeCodeからTypeオブジェクトを取得する方法は何かありますか?

    これは 難しいですね 私では無理かも・・

    2006年11月6日 8:11
  • インチキくさい方法ですが、以下コードでも取得できるようです

    Type type =

    Type.GetType(string.Format(CultureInfo.InvariantCulture, "System.{0}", Enum.GetName(typeof(TypeCode), typeCode)));

     

     

    2006年11月6日 8:38
  •         Dim bb As Integer = TypeCode.Int16
            Dim dd As String = "123"
            Dim cc As Object = Convert.ChangeType(dd, bb)

    どう使われるのか分かりませんが

    こんな感じで TypeCodeでCtypeの代わりのような使い方ができるようですが・・

    2006年11月6日 9:00
  • 素人くさい 方法かもしれませんが

            Dim cod As Integer = タイプコード
            Dim ty As Type
            Select Case cod
                Case 3
                    ty = GetType(Boolean)
                Case 6
                    ty = GetType(Byte)
                Case 4
                    ty = GetType(Char)
                Case 16
                    ty = GetType(DateTime)
                Case 2
                    ty = GetType(DBNull)
                Case 15
                    ty = GetType(Decimal)
                Case 14
                    ty = GetType(Double)
                Case 7
                    ty = GetType(Int16)
                Case 9
                    ty = GetType(Int32)
                Case 11
                    ty = GetType(Int64)
                Case 1
                    ty = GetType(Object)
                Case 5
                    ty = GetType(SByte)
                Case 13
                    ty = GetType(Single)
                Case 18
                    ty = GetType(String)
                Case 8
                    ty = GetType(UInt16)
                Case 10
                    ty = GetType(UInt32)
                Case 12
                    ty = GetType(UInt64)
            End Select

     

    2006年11月6日 9:37
  •  zilch さんからの引用

    Type type =
    Type.GetType(string.Format(CultureInfo.InvariantCulture, "System.{0}", Enum.GetName(typeof(TypeCode), typeCode)));

    や、やっぱり"System."を文字列でくっつける方法ですね。
    実は私も「最悪はこの方法で逃げるしかないかな」と思って、とりあえずはFullNameと等価な文字列を作成する関数を作成していたところです。
    でもzilchさんの方法のほうが1行で終わってすっきりしそうですね。

    2006年11月6日 9:39
  •  かずboo さんからの引用
     
            Dim cod As Integer = タイプコード
            Dim ty As Type
            Select Case cod
                Case 3
                    ty = GetType(Boolean)
                Case 6
                    ty = GetType(Byte)
                Case 4
                    ty = GetType(Char)
                Case 16
                    ty = GetType(DateTime)
                Case 2
                    ty = GetType(DBNull)
                Case 15
                    ty = GetType(Decimal)
                Case 14
                    ty = GetType(Double)
                Case 7
                    ty = GetType(Int16)
                Case 9
                    ty = GetType(Int32)
                Case 11
                    ty = GetType(Int64)
                Case 1
                    ty = GetType(Object)
                Case 5
                    ty = GetType(SByte)
                Case 13
                    ty = GetType(Single)
                Case 18
                    ty = GetType(String)
                Case 8
                    ty = GetType(UInt16)
                Case 10
                    ty = GetType(UInt32)
                Case 12
                    ty = GetType(UInt64)
            End Select

    zilchさんへレスしていたら、かずbooさんからも私が作成中の"関数"と同じような関数のレスが・・・(爆

     かずboo さんからの引用
     
            Dim bb As Integer = TypeCode.Int16
            Dim dd As String = "123"
            Dim cc As Object = Convert.ChangeType(dd, bb)
    どう使われるのか分かりませんが
    こんな感じで TypeCodeでCtypeの代わりのような使い方ができるようですが・・

    型キャストも行いたいのですが、Typeクラスのメソッド(具体的にはType.InvokeMember()です)も使用したいので
    Typeオブジェクトが欲しいのです。

    2006年11月6日 9:48
  • "System."をくっつけるのは場当たり的ですし、使用可能な型も制御できる事を考えるとコリン星人さんの方法で新しい enum を作って自作関数で型情報を返した方が良さそうですね。



    2006年11月6日 9:55
  • 既に古い記事となってますが私も同じ事で嵌って検索でココを見みつけたものの
    明確な結論が出てないまま風化してるようなので後から見た人がまた同じ事に嵌
    らないように調べて分かった事を記述しておきます。

    とりあえずまず先に単純にTypeCodeをType型に変換する簡単な方法

    Dim cod as TypeCode

    Select Case cod でチェックすべきは

    TypeCode.DateTime, TypeCode.DBNull, TypeCode.Empty, TypeCode.Object

    だけでかまいません。他は↓のように 0 を変換してオブジェクトさえ取得して
    しまえばGetTypeでType型を取得する事ができます。

    Dim typ As Type = Convert.ChangeType(0, cod).GetType

     


    ------------------------------------------------------------------------------------------------------
    Type型のプロパティをプロパティウィンドウで設定したいの本題はココから
    ------------------------------------------------------------------------------------------------------

    'まずTypeConverterから派生させてリスト表示させる為のコンバーターを作成します。
    '必要となる型や不要な型はコンストラクタ部分のType配列を適当に変更して下さい。

    Friend Class ValueTypeConverter
        Inherits System.ComponentModel.TypeConverter
        Private _ValueTypesDictionary As New Dictionary(Of String, System.Type)

        Public Sub New()
            MyBase.New()
            Dim typs() As Type = New System.Type() _
                                {GetType(Boolean), GetType(Byte), GetType(Char), _
                                 GetType(DateTime), GetType(Decimal), GetType(Double), _
                                 GetType(Guid), GetType(Int16), GetType(Int32), _
                                 GetType(Int64), GetType(SByte), GetType(Single), _
                                 GetType(String), GetType(TimeSpan), GetType(UInt16), _
                                 GetType(UInt32), GetType(UInt64)}

            For Each typ As System.Type In typs
                Me._ValueTypesDictionary(typ.ToString) = typ
            Next
        End Sub

        'スタンダードリストをサポートしている事を告げる
        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 System.ComponentModel.TypeConverter.StandardValuesCollection
            Dim svc As New StandardValuesCollection(Me._ValueTypesDictionary.Keys)
            Return svc
        End Function

        '文字からの変換は可能であるとする
        Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
            If sourceType Is GetType(String) Then Return True
            Return MyBase.CanConvertFrom(context, sourceType)
        End Function

        '文字キーがタイプ型として認識可能な場合はコンストラクタで初期化したDictionaryの値のType型に変換してやる
        Public 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
                Dim strKey As String = Strings.StrConv(value.ToString.Trim, VbStrConv.Narrow Or VbStrConv.ProperCase)
                If Me._ValueTypesDictionary.ContainsKey(strKey) Then
                    Return Me._ValueTypesDictionary.Item(strKey)
                End If
            End If
            Return MyBase.ConvertFrom(context, culture, value)
        End Function

        '文字キーやType型が該当の型であるかをチェックさせる
        Public Overrides Function IsValid(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal value As Object) As Boolean
            If TypeOf value Is String Then
                Dim strKey As String = Strings.StrConv(value.ToString.Trim, VbStrConv.Narrow Or VbStrConv.ProperCase)
                Return Me._ValueTypesDictionary.ContainsKey(strKey)
            ElseIf TypeOf value Is System.Type Then
                Return Me._ValueTypesDictionary.ContainsValue(value)
            End If
            Return MyBase.IsValid(context, value)
        End Function
    End Class

    'コンバーターはココまで
    ------------------------------------------------------------------------------------------------------

     

    あとはプロパティウィンドウで設定したいType型のプロパティの属性にコンバーター
    さえ指定してしまえばOKです。

     

     

        Private _DataType As System.Type = GetType(String)

        <Category("Data"), _
         Description("~~~"), _
         TypeConverter(GetType(ValueTypeConverter))> _
        Public Property DataType() As System.Type
            Get
                Return Me._DataType
            End Get
            Set(ByVal value As System.Type)
                Me._DataType = value
            End Set
        End Property


                                     - 以上 -

    2007年9月19日 3:59
  • 書き忘れがあったので追加です。
    コンバーターでせっかくIsValidをオーバーライドしたのでプロパティのセッター部分で
    の使い方は↓のようにします。


        Public Property DataType() As System.Type
            Get
                Return Me._DataType
            End Get
            Set(ByVal value As System.Type)
                If Type.Equals(Me._DataType, value) Then Return
                Dim cnv As New frd.cls.ValueTypeConverter
                If Not cnv.IsValid(value) Then
                    Throw New ArgumentException("有効な型ではありません。")
                End If
                Me._DataType = value
            End Set
        End Property

     

    2007年9月19日 4:22
  • 投稿前に確認もせずにちょっと修正した部分がバグってました・・・

     

    Dim strKey As String = Strings.StrConv(value.ToString.Trim, VbStrConv.Narrow Or VbStrConv.ProperCase)

    これじゃぁ System.DateTime などが System.Datetime みたいになってダメですね(^^;

     

    Dim strKey As String = value.ToString

    こんだけでじゅうぶんなんですけどなんとなくちゃんとと思ったのが裏目でした(^^;;

     

     

    ちょっと強引な書き方だけどバグ部の下に↓追加すればちゃんと動きます!w

    strKey = strKey.Replace("time", "Time").Replace("byte", "Byte").Replace("span", "Span").Replace("int", "Int")

     

     

    2007年9月19日 11:37
  • さらにいろいろやってて解った事があるので補足しておきます。

    スタンダードリストとして渡す時にわざわざ文字にして渡す必要はないみたいです。


    '-----------------------------------------------------------------------------------
    Friend Class TypeSelectConverter
        Inherits System.ComponentModel.TypeConverter

     

    #Region "プライベート変数"

     

        Private _TypLst As New List(Of Type)(New System.Type() _
                            {GetType(Boolean), GetType(Byte), GetType(Char), _
                             GetType(DateTime), GetType(Decimal), GetType(Double), _
                             GetType(Guid), GetType(Int16), GetType(Int32), _
                             GetType(Int64), GetType(SByte), GetType(Single), _
                             GetType(String), GetType(TimeSpan), GetType(UInt16), _
                             GetType(UInt32), GetType(UInt64)})

     

    #End Region

     

    #Region "オーバーライド"

     

        'スタンダードリストをサポートしている事を告げる
        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 System.ComponentModel.TypeConverter.StandardValuesCollection
            Return New StandardValuesCollection(Me._TypLst)
        End Function

     

        '排他リストである事を告げる
        Public Overrides Function GetStandardValuesExclusive _
                    (ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
            Return True
        End Function

     

        '文字からの変換は可能であるとする
        Public Overrides Function CanConvertFrom _
                    (ByVal context As System.ComponentModel.ITypeDescriptorContext, _
                     ByVal sourceType As System.Type) As Boolean
            If sourceType Is GetType(String) Then Return True
            Return MyBase.CanConvertFrom(context, sourceType)
        End Function

     

        'リストにある場合のみ変換してやる
        Public 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
                Dim typ As Type = Type.GetType(value, False, True)
                If Me._TypLst.Contains(typ) Then Return typ
            End If
            Return MyBase.ConvertFrom(context, culture, value)
        End Function

     

        'リストにある場合はTrueそれ以外はFalse
        Public Overrides Function IsValid _
                    (ByVal context As System.ComponentModel.ITypeDescriptorContext, _
                     ByVal value As Object) As Boolean
            Return Me._TypLst.Contains(value)
        End Function

     

    #End Region

     

    End Class
    '-----------------------------------------------------------------------------------

    2007年9月21日 5:18