System.ComponentModel.TypeConverter

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

System.ComponentModel.TypeConverter

Сообщение FireFenix » 21.02.2010 (Вс) 17:54

Собсно интересуют методы ConvertTo и ConvertFrom класса System.ComponentModel.TypeConverter...

Имею PropertyGrid, пытаюсь пределать выпадающий список (1,2,3) к параметру объекта типа Int32...

Поидее (как я понял из всего нагугленного):
ConvertFrom - вызывается при приведении элемента списка к String
ConvertTo - Вызывается при приведении String к параметру объекта

Переопределил методы, поставил вывод Console.Werite и получил
Код: Выделить всё
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)1
ConvertTo: (System.Int32 -> System.String)2
ConvertTo: (System.Int32 -> System.String)3
ConvertTo: (System.Int32 -> System.String)1
ConvertTo: (System.Int32 -> System.String)2
ConvertTo: (System.Int32 -> System.String)3
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.String -> System.String)
ConvertFrom :
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)0
ConvertTo: (System.Int32 -> System.String)0


Почему столько беспредельных вызовов на выбор одного элемента?
И что же всё-таки делают ConvertTo и ConvertFrom?
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re: System.ComponentModel.TypeConverter

Сообщение Dmitriy2003 » 21.02.2010 (Вс) 20:31

FireFenix писал(а):Имею PropertyGrid, пытаюсь пределать выпадающий список (1,2,3) к параметру объекта типа Int32...

Код: Выделить всё
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        internal enum AccessLevel : int { Gast, DefaultUser, Administrator}

        internal class Person
        {
            private AccessLevel accessLevel = AccessLevel.DefaultUser;

            [DefaultValue(typeof(AccessLevel), "DefaultUser")]
            public AccessLevel CurrentAccessLevel
            {
                get { return this.accessLevel; } set { this.accessLevel = value; }
            }
        }

        public Form1()
        {
            InitializeComponent();
            Person person = new Person();
            PropertyGrid personProperties = new PropertyGrid();
            personProperties.SelectedObject = person;
            personProperties.Dock = DockStyle.Fill;
            Controls.Add(personProperties);
        }   
    }
}

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: System.ComponentModel.TypeConverter

Сообщение FireFenix » 21.02.2010 (Вс) 23:13

Вообще идея была : в свойстве показывать ComboBox с динамически заполняемым списком (к примеру с элементами 1,2,3), причём сопоставлять текстовое значение с индексом и индекс уже заносить в свойства объекта...

Но к тому же меня поразило обилие лишних вызовов преобразований... Интересно зачем они....
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re: System.ComponentModel.TypeConverter

Сообщение Dmitriy2003 » 22.02.2010 (Пн) 1:07

FireFenix писал(а):Вообще идея была : в свойстве показывать ComboBox с динамически заполняемым списком (к примеру с элементами 1,2,3), причём сопоставлять текстовое значение с индексом и индекс уже заносить в свойства объекта...

Какой смысл, заполнять элементами типа - (1,2,3) - если можно (нужно) сразу объектами, и следовательно ничего потом сопоставлять не нужно.
FireFenix писал(а):Но к тому же меня поразило обилие лишних вызовов преобразований... Интересно зачем они....

Покажи код - который эти "лишние" преобразования вызывает.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: System.ComponentModel.TypeConverter

Сообщение FireFenix » 22.02.2010 (Пн) 8:51

Dmitriy2003 писал(а):
FireFenix писал(а):Вообще идея была : в свойстве показывать ComboBox с динамически заполняемым списком (к примеру с элементами 1,2,3), причём сопоставлять текстовое значение с индексом и индекс уже заносить в свойства объекта...

Какой смысл, заполнять элементами типа - (1,2,3) - если можно (нужно) сразу объектами, и следовательно ничего потом сопоставлять не нужно.
Имеется база... в таблице для каждой текстовой записи сопоставлен ID... Для выбора объекта, мне нужно получить его ID

Код: Выделить всё
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Globalization
Imports System.Collections.Generic

Класс динамического Объекта
Код: Выделить всё
Public Class DynamicPropertyObject : Implements ICustomTypeDescriptor
    Private _Filter As String = String.Empty
    Private _FilteredPropertyDescriptors As New PropertyDescriptorCollection(Nothing)
    Private _FullPropertyDescriptors As New PropertyDescriptorCollection(Nothing)

    Public Sub AddProperty(ByVal Type As Types.DataType, ByVal Id As Integer, ByVal Text As String, ByVal Name As String, ByVal Description As String, ByVal Category As String, ByVal [ReadOnly] As Boolean)
        Select Case Type
            Case Types.DataType.Integer
                Dim Value As Integer = 0

                If Not Text Is Nothing OrElse Not Text = String.Empty Then
                    Try
                        Value = Convert.ToInt32(Text)
                    Catch ex As Exception
                        MsgBox("Ошибка СУБД: Несоответствие типа Intger (32-bit) параметра " & Name & " = " & Value)
                    End Try
                End If

                AddProperty(Of Integer)(Id.ToString, Value, Name, Description, Category, [ReadOnly], Nothing)

            Case Types.DataType.Single
                Dim Value As Single = 0.0F

                If Not Text Is Nothing OrElse Not Text = String.Empty Then
                    Try
                        Value = Convert.ToSingle(Text)
                    Catch ex As Exception
                        MsgBox("Ошибка СУБД: Несоответствие типа Single параметра " & Name)
                    End Try
                End If

                AddProperty(Of Single)(Id.ToString, Value, Name, Description, Category, [ReadOnly], Nothing)

            Case Types.DataType.String
                AddProperty(Of String)(Id.ToString, Text, Name, Description, Category, [ReadOnly], Nothing)

            Case Types.DataType.Boolean
                Dim Value As Boolean = False

                If Not Text Is Nothing OrElse Not Text = String.Empty Then
                    Try
                        Value = Convert.ToBoolean(Text)
                    Catch ex As Exception
                        MsgBox("Ошибка СУБД: Несоответствие типа Boolean параметра " & Name)
                    End Try
                End If

                AddProperty(Of Boolean)(Id.ToString, Value, Name, Description, Category, [ReadOnly], Nothing)

            Case Types.DataType.Date
                Dim Value As Date = Now

                AddProperty(Of Date)(Id.ToString, Value, Name, Description, Category, [ReadOnly], Nothing)
        End Select
    End Sub

    Public Sub AddProperty(Of T)(ByVal Name As String, ByVal Value As T, ByVal DisplayName As String, ByVal Description As String, ByVal Category As String, ByVal [ReadOnly] As Boolean, ByVal Attributes As IEnumerable(Of Attribute))
        Dim Attrs = If(Attributes Is Nothing, New List(Of Attribute)(), New List(Of Attribute)(Attributes))

        If Not String.IsNullOrEmpty(DisplayName) Then
            Attrs.Add(New DisplayNameAttribute(DisplayName))
        End If

        If Not String.IsNullOrEmpty(Description) Then
            Attrs.Add(New DescriptionAttribute(Description))
        End If

        If Not String.IsNullOrEmpty(Category) Then
            Attrs.Add(New CategoryAttribute(Category))
        End If

        If [ReadOnly] Then
            Attrs.Add(New ReadOnlyAttribute(True))
        End If

        If TypeOf Value Is Integer Then
            Value = Nothing

            'Attrs.Add(New EditorAttribute(GetType(MultilineStringEditor), GetType(Drawing.Design.UITypeEditor)))
            'Эксперементы над подопытным
            Attrs.Add(New TypeConverterAttribute(GetType(MaterialTypeConverter)))
        End If

        _FullPropertyDescriptors.Add(New GenericPropertyDescriptor(Of T)(Name, Value, Attrs.ToArray()))
    End Sub

    Public Sub AddProperty(Of T)(ByVal Name As String, ByVal Value As T, ByVal DisplayName As String, ByVal Description As String, ByVal Category As String, ByVal [ReadOnly] As Boolean)
        AddProperty(Of T)(Name, Value, DisplayName, Description, Category, [ReadOnly], Nothing)
    End Sub

    Public Sub RemoveProperty(ByVal PropertyName As String)
        Dim Descriptor = _FullPropertyDescriptors.Find(PropertyName, True)

        If Not Descriptor Is Nothing Then
            _FullPropertyDescriptors.Remove(Descriptor)
        End If
    End Sub

    Public Property Filter() As String
        Get
            Return _Filter
        End Get

        Set(ByVal Value As String)
            _Filter = Value.Trim().ToLower()

            If _Filter.Length <> 0 Then
                FilterProperties(_Filter)
            End If
        End Set
    End Property

    Private Sub FilterProperties(ByVal Filter As String)
        _FilteredPropertyDescriptors.Clear()

        For Each Descriptor As PropertyDescriptor In _FullPropertyDescriptors
            If Descriptor.Name.ToLower().IndexOf(Filter) > -1 Then
                _FilteredPropertyDescriptors.Add(Descriptor)
            End If
        Next
    End Sub

    Public Property Item(ByVal PropertyName As String) As Object
        Get
            Return GetPropertyValue(PropertyName)
        End Get

        Set(ByVal Value As Object)
            SetPropertyValue(PropertyName, Value)
        End Set
    End Property

    Public Function Items() As PropertyDescriptorCollection
        Return _FullPropertyDescriptors
    End Function

    Private Function GetPropertyValue(ByVal PropertyName As String) As Object
        Dim Descriptor = _FullPropertyDescriptors.Find(PropertyName, True)

        If Not Descriptor Is Nothing Then
            Return Descriptor.GetValue(Nothing)
        End If

        Return Nothing
    End Function

    Private Sub SetPropertyValue(ByVal PropertyName As String, ByVal Value As Object)
        Dim Descriptor = _FullPropertyDescriptors.Find(PropertyName, True)

        If Not Descriptor Is Nothing Then
            Descriptor.SetValue(Nothing, Value)
        End If
    End Sub

#Region "Implementation of ICustomTypeDescriptor"
    Public Function GetConverter() As System.ComponentModel.TypeConverter Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter
        Return TypeDescriptor.GetConverter(Me, True)
    End Function

    Public Function GetEvents(ByVal attributes As System.Attribute()) As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return TypeDescriptor.GetEvents(Me, attributes, True)
    End Function

    Public Function GetEvents() As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
        Return TypeDescriptor.GetEvents(Me, True)
    End Function

    Public Function GetComponentName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName
        Return TypeDescriptor.GetComponentName(Me, True)
    End Function

    Public Function GetPropertyOwner(ByVal pd As System.ComponentModel.PropertyDescriptor) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner
        Return Me
    End Function

    Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes
        Return TypeDescriptor.GetAttributes(Me, True)
    End Function

    Public Function GetProperties(ByVal attributes As System.Attribute()) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        If _Filter.Length <> 0 Then
            Return _FilteredPropertyDescriptors
        Else
            Return _FullPropertyDescriptors
        End If
    End Function

    Public Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
        Return GetProperties(New Attribute(-1) {})
    End Function

    Public Function GetEditor(ByVal editorBaseType As System.Type) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor
        Return TypeDescriptor.GetEditor(Me, editorBaseType, True)
    End Function

    Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty
        Return TypeDescriptor.GetDefaultProperty(Me, True)
    End Function

    Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent
        Return TypeDescriptor.GetDefaultEvent(Me, True)
    End Function

    Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName
        Return TypeDescriptor.GetClassName(Me, True)
    End Function
#End Region

End Class

TypeConverter
Код: Выделить всё
Class MaterialTypeConverter : Inherits Int32Converter
    'Извращение с поиском по 2м критериям
    Private Dictionary_Output As New Dictionary(Of Integer, String)
    Private Dictionary_Input As New Dictionary(Of String, Integer)
    Private Collection As New Collection

    Public Sub New()
        Dim Item As KeyValuePair(Of Integer, String)

        Dictionary_Output.Add(1, "qwer")
        Dictionary_Output.Add(2, "asdf")
        Dictionary_Output.Add(3, "zxcv")

        For Each Item In Dictionary_Output
            Dictionary_Input.Add(Item.Value, Item.Key)
            Collection.Add(Item.Key)
        Next
    End Sub

    Public Overrides Function GetStandardValues(ByVal context As ITypeDescriptorContext) As TypeConverter.StandardValuesCollection
        Return New TypeConverter.StandardValuesCollection(Collection)
    End Function

    Public Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object) As Object
        If Not value Is Nothing Then
            Console.WriteLine("ConvertFrom : " & value.ToString)
            'Return Dictionary_Output(Convert.ToInt32(value)).ToString
            'Return CInt(value)
        End If

        Return value.ToString
    End Function

    Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object

        Console.WriteLine("ConvertTo: (" & value.GetType.ToString & " -> " & destinationType.ToString & ")" & value.ToString)

        If Not value Is Nothing Then
            Select Case destinationType.GetType
                Case GetType(Integer)
                    Select Case value.GetType
                        Case GetType(Integer)
                            Return value
                        Case GetType(String)
                            Return value.ToString
                    End Select

                Case GetType(String)
                    Select Case value.GetType
                        Case GetType(Integer)
                            Return Convert.ToInt32(value)
                        Case GetType(String)
                            Return value
                    End Select
            End Select
        End If

        Return Nothing
    End Function

    Public Overrides Function GetStandardValuesExclusive(ByVal context As ITypeDescriptorContext) As Boolean
        Return True 'Выбор только из списка
    End Function

    Public Overrides Function GetStandardValuesSupported(ByVal context As ITypeDescriptorContext) As Boolean
        Return True 'Выбор из списка
    End Function

    Public Class Node
        Friend Key As String
        Friend [Next] As Node
        Friend Prev As Node
        Friend Value As Object

        Friend Sub New(ByVal Key As String, ByVal Value As Object)
            Me.Value = Value
            Me.Key = Key
        End Sub
    End Class
End Class

И эту дьявольскую машину запускает
Код: Выделить всё
Private PropertyObject As DynamicPropertyObject

PropertyObject.AddProperty(Types.DataType.Integer, 9999, Nothing, "zxcvzxcv", "cnbcnb", "dfhdfgh", False)

PropertyGrid.SetObject = PropertyObject


Dmitriy2003 писал(а):
FireFenix писал(а):Но к тому же меня поразило обилие лишних вызовов преобразований... Интересно зачем они....

Покажи код - который эти "лишние" преобразования вызывает.

Кофеварка PropertyGrid сама вызывает непонятное количество раз мой TypeConvertor
Исходя из моих предположений - должно быть 2 или 4 раза, но не более как я вывесил в логе в первом посте (на действиях : вызов выпадающего списка + выбор элемента)
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re: System.ComponentModel.TypeConverter

Сообщение Dmitriy2003 » 22.02.2010 (Пн) 11:42

FireFenix писал(а):Имеется база... в таблице для каждой текстовой записи сопоставлен ID... Для выбора объекта, мне нужно получить его ID

FireFenix писал(а):PropertyObject.AddProperty(Types.DataType.Integer, 9999, Nothing, "zxcvzxcv", "cnbcnb", "dfhdfgh", False)

Очень информативно :|

Читая это - 1, 2 - мне ясно что, зачем и почему человек хотел сделать, однако начинает надоедать вытягивать из вас информацию по кусочку, Очень хочется узнать почему - "Кофеварка PropertyGrid сама вызывает непонятное количество раз ваш TypeConvertor" - ildasm.exe - > System.Windows.Forms.dll

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: System.ComponentModel.TypeConverter

Сообщение FireFenix » 22.02.2010 (Пн) 18:05

Dmitriy2003 писал(а):
FireFenix писал(а):Имеется база... в таблице для каждой текстовой записи сопоставлен ID... Для выбора объекта, мне нужно получить его ID

FireFenix писал(а):PropertyObject.AddProperty(Types.DataType.Integer, 9999, Nothing, "zxcvzxcv", "cnbcnb", "dfhdfgh", False)

Очень информативно :|

Ну нада было вначале протестировать без БД, вот и забивал случайными значениями :|

Dmitriy2003 писал(а):Читая это - 1, 2 - мне ясно что, зачем и почему человек хотел сделать

Прочитав это, я так и не понял зачем PGrid вызывать столько раз TypeConverter

Dmitriy2003 писал(а):однако начинает надоедать вытягивать из вас информацию по кусочку

Эм... я попросил совета - почему оно работает так, а не иначе... и как бы количество вызовов моего класса не сильно зависит от моего класса, ну и на крайний случай может я что-то у пустил, но требования для нахождения решения можно было бы написать сразу без "вытягивания из меня"

Dmitriy2003 писал(а):Очень хочется узнать почему - "Кофеварка PropertyGrid сама вызывает непонятное количество раз ваш TypeConvertor" - ildasm.exe - > System.Windows.Forms.dll

Я вскрывал рефлектором, но религию работы PropertyGrid не понял... а уж темболее накой ему вызывать столько ненужных преобразований :cry:
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16

    TopList  
cron