Completed
Last Updated: 12 Apr 2016 06:52 by ADMIN
ADMIN
Dess | Tech Support Engineer, Principal
Created on: 31 Mar 2016 09:28
Category: GridView
Type: Bug Report
0
FIX. RadGridView - InvalidCastException when using a GridSpinEditor and a custom TypeConverter
To reproduce:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Me.RadGridView1.AutoGenerateColumns = False

    Dim column = New GridViewTextBoxColumn
    column.Name = "Name"
    column.FieldName = "ChildItem"
    column.DataType = GetType(CustomItem)
    column.DataTypeConverter = New CustomItemTypeConverter()

    Me.RadGridView1.Columns.Add(column)
    Me.RadGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill

    Dim objects =
        {
            New CustomContainer With {.ChildItem = New CustomItem With {.Name = "A"}},
            New CustomContainer With {.ChildItem = New CustomItem With {.Name = "B"}},
            New CustomContainer With {.ChildItem = New CustomItem With {.Name = "C"}}
        }

    Me.RadGridView1.DataSource = objects
End Sub

Private Sub RadGridView_EditorRequired(sender As Object, e As EditorRequiredEventArgs) Handles RadGridView1.EditorRequired
    e.EditorType = GetType(GridSpinEditor)
End Sub

Class CustomContainer
    Public Property ChildItem As CustomItem
End Class

Class CustomItem
    Public Property Name As String
End Class

Class CustomItemTypeConverter
Inherits TypeConverter

    Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
        If sourceType = GetType(Decimal) Then
            Return True
        End If

        Return MyBase.CanConvertFrom(context, sourceType)
    End Function

    Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean
        If destinationType = GetType(Decimal) OrElse destinationType = GetType(String) OrElse destinationType = GetType(CustomItem) Then
            Return True
        End If

        Return MyBase.CanConvertTo(context, destinationType)
    End Function

    Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, _
                                        value As Object, destinationType As Type) As Object
        If TypeOf value Is CustomItem Then
            Dim customValue = DirectCast(value, CustomItem)

            If destinationType = GetType(Decimal) Then
                Return Microsoft.VisualBasic.AscW(customValue.Name.Chars(0))
            ElseIf destinationType = GetType(String) Then
                Return customValue.Name
            ElseIf destinationType = GetType(CustomItem) Then
                Return customValue
            Else
                Return MyBase.ConvertTo(context, culture, value, destinationType)
            End If
        End If

        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function

    Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As System.Globalization.CultureInfo, value As Object) As Object
        If TypeOf value Is Decimal Then
            Dim decValue = DirectCast(value, Decimal)
            Dim intValue = CInt(decValue)
            Dim charValue = Microsoft.VisualBasic.ChrW(intValue)

            Return New CustomItem With {.Name = New String(charValue, 1)}
        End If

        Return MyBase.ConvertFrom(context, culture, value)
    End Function

End Class


Workaround:

Public Class MyEditor
    Inherits GridSpinEditor

    Public Overrides ReadOnly Property IsModified() As Boolean
        Get
            If Me.originalValue Is Nothing Then
                Return (Me.Value IsNot Nothing AndAlso Me.Value <> DBNull.Value)
            End If

            If Me.Value Is Nothing Then
                Return (Me.originalValue IsNot Nothing AndAlso Me.originalValue <> DBNull.Value)
            End If
            Dim column As GridViewDataColumn = (DirectCast(Me.OwnerElement, GridDataCellElement)).ColumnInfo
            If column.DataTypeConverter IsNot Nothing AndAlso column.DataTypeConverter.CanConvertTo(Me.OwnerElement, GetType(Decimal)) Then
                Return Not column.DataTypeConverter.ConvertTo(Me.OwnerElement, column.FormatInfo, Me.originalValue, GetType(Decimal)).Equals(Convert.ToDecimal(Me.Value))
            End If

            Return Not Convert.ToDecimal(Me.originalValue).Equals(Convert.ToDecimal(Me.Value))
        End Get
    End Property
End Class


Private Sub RadGridView_EditorRequired(sender As Object, e As EditorRequiredEventArgs) Handles RadGridView1.EditorRequired
    e.EditorType = GetType(MyEditor)
End Sub
0 comments