This is a migrated thread and some comments may be shown as answers.

[Solved] Problem when sorting bindable custom collection

1 Answer 139 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Avidan
Top achievements
Rank 1
Avidan asked on 25 Oct 2009, 04:17 PM
Hi,

A. I bound a radGrid control to a custom collection called FactoryList(of Tkey).
B. The FactoryList control derived from BindingList (of Tkey) and implements ITypedList as follow:
    1. The GetItemProperties return a collection of ColumnPropertyDescriptor objects, each is derived from PropertyDescriptor class
    2. The ColumnPropertyDescriptor class exposes information based on DataColumn meta-data i.e. ColumnName, ColumnType, and also handle SetValue and Get Value methods.
 
C. A FactoryList instance contains objects that are derived from a base class called BaseEntity. The BaseEntity class implements

ICustomTypeDescriptor, where the GetItemProperties retruns a collection of ColumnPropertyDescriptor same as the FactoryList class does.
D. I use the NeedDataSource event to bind the FactoryList to the radGrid  


All works fine, till I sort the grid rows by clicking on one of the grid column headers. In that case I got the following error:

No property or field 'LST_NAME' exists in type 'Object'  

 -  'LST_NAME' is one the columns I was trying to sort


radGrid:

<

 

telerik:RadGrid ID="grdCustomLists" runat="server" AllowPaging="True"

 

 

    AllowSorting="True" AutoGenerateColumns="False" AutoGenerateDeleteColumn="True"

 

 

    AutoGenerateEditColumn="True" GridLines="None"

 

 

    DataMember="esmBOA.SystemList">

 

<

 

MasterTableView CommandItemDisplay="Top" DataKeyNames="LST_ID" EditMode="InPlace"

 

 

    DataMember="esmBOA.SystemList">

 

 

<CommandItemSettings AddNewRecordText="New List" />

 

<

 

RowIndicatorColumn>

 

<

 

HeaderStyle Width="20px"></HeaderStyle>

 

</

 

RowIndicatorColumn>

 

<

 

ExpandCollapseColumn>

 

<

 

HeaderStyle Width="20px"></HeaderStyle>

 

</

 

ExpandCollapseColumn>

 

 

<Columns>

 

 

<telerik:GridBoundColumn DataField="LST_ID" HeaderText="LST_ID" ReadOnly="True"

 

 

SortExpression="LST_ID" UniqueName="LST_ID" Visible="False"

 

 

Display="False">

 

 

</telerik:GridBoundColumn>

 

 

<telerik:GridBoundColumn DataField="LST_NAME" HeaderText="Name"

 

 

SortExpression="LST_NAME" UniqueName="LST_NAME">

 

 

</telerik:GridBoundColumn>

 

 

<telerik:GridBoundColumn DataField="LST_DSC" HeaderText="Description"

 

 

SortExpression="LST_DSC" UniqueName="LST_DSC">

 

 

</telerik:GridBoundColumn>

 

 

<telerik:GridCheckBoxColumn DataField="LST_IS_SYSTEM" DataType="System.Boolean"

 

 

HeaderText="LST_IS_SYSTEM" SortExpression="LST_IS_SYSTEM"

 

 

UniqueName="LST_IS_SYSTEM" Visible="False" Display="False" ReadOnly="True">

 

 

</telerik:GridCheckBoxColumn>

 

 

<telerik:GridCheckBoxColumn DataField="LST_CAN_EDIT" DataType="System.Boolean"

 

 

HeaderText="LST_CAN_EDIT" SortExpression="LST_CAN_EDIT"

 

 

UniqueName="LST_CAN_EDIT" Visible="False" Display="False" ReadOnly="True">

 

 

</telerik:GridCheckBoxColumn>

 

 

<telerik:GridCheckBoxColumn DataField="LST_CAN_DELETE"

 

 

DataType="System.Boolean" HeaderText="LST_CAN_DELETE"

 

 

SortExpression="LST_CAN_DELETE" UniqueName="LST_CAN_DELETE"

 

 

Visible="False" Display="False" ReadOnly="True">

 

 

</telerik:GridCheckBoxColumn>

 

 

<telerik:GridCheckBoxColumn DataField="LST_IS_DELETED"

 

 

DataType="System.Boolean" HeaderText="LST_IS_DELETED"

 

 

SortExpression="LST_IS_DELETED" UniqueName="LST_IS_DELETED"

 

 

Visible="False" Display="False" ReadOnly="True">

 

 

</telerik:GridCheckBoxColumn>

 

 

</Columns>

 

</

 

MasterTableView>

 

 

<ClientSettings>

 

 

<Selecting AllowRowSelect="True" />

 

 

</ClientSettings>

 

 

</telerik:RadGrid>

 

ColumnPropertyDescriptor Class (VB) - SystemField class stores the DataColumn meta-data

Public

 

Class ColumnPropertyDescriptor

 

 

Inherits System.ComponentModel.PropertyDescriptor

 

#Region

 

"Attributes"

 

 

    Private _column As SystemField

 

#End

 

Region

 

#Region

 

"Constractor"

 

 

 

Public Sub New(ByVal column As SystemField)

 

 

        MyBase.New(column.ColumnName, Nothing)

 

        _column = column

 

End Sub

 

#End

 

Region

 

#Region

 

"Properties"

 

 

Public Property Column() As SystemField

 

 

Get

 

 

    Return _column

 

 

End Get

 

 

Set(ByVal value As SystemField)

 

_column = value

 

End Set

 

 

End Property

 

#End

 

Region

 

#Region

 

"PropertyDescriptor Overrides"

 

#Region

 

"Properties"

 

 

Public Overrides ReadOnly Property Converter() As System.ComponentModel.TypeConverter

 

 

Get

 

 

    Return ComponentModel.TypeDescriptor.GetConverter(Me.PropertyType)

 

 

End Get

 

 

End Property

 

 

Public Overrides ReadOnly Property DisplayName() As String

 

 

Get

 

 

    Return _column.Properties.Caption

 

 

End Get

 

 

End Property

 

 

Public Overrides ReadOnly Property Name() As String

 

 

Get

 

 

    Return _column.ColumnName

 

 

End Get

 

 

End Property

 

 

Public Overrides ReadOnly Property ComponentType() As System.Type

 

 

Get

 

 

    Return Me.PropertyType

 

 

End Get

 

 

End Property

 

 

Public Overrides ReadOnly Property IsReadOnly() As Boolean

 

 

Get

 

 

    Return _column.Properties.IsEdit

 

 

End Get

 

 

End Property

 

 

Public Overrides ReadOnly Property PropertyType() As System.Type

 

 

Get

 

 

    Return _column.SystemColumnType

 

 

End Get

 

 

End Property

 

#End

 

Region

 

#Region

 

"Public Methods"

 

 

Public Overrides Function CanResetValue(ByVal component As Object) As Boolean

 

 

    Return False

 

 

End Function

 

 

 

Public Overrides Function GetValue(ByVal component As Object) As Object

 

 

 

    Dim item As BaseEntity = CType(component, BaseEntity)

 

 

    Return item.Field(Me._column.ColumnName)

 

 

End Function

 

 

 

 

Public Overrides Sub ResetValue(ByVal component As Object)

 

 

    Throw New NotImplementedException

 

 

End Sub

 

 

Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)

 

 

    Dim item As BaseEntity = CType(component, BaseEntity)

 

    item.Field(

Me._column.ColumnName) = value ' value is stored in a key dictionary

 

 

End Sub

 

 

Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean

 

 

    Return False

 

 

End Function

 

#End

 

Region

 

 

#End

 

Region

 

End

 

Class

 



BaseEntity Class:

Imports

 

System.ComponentModel

 

Public

 

Class BaseEntity

 

 

        Implements ICustomTypeDescriptor

 

#Region

 

"Data Members"

 

 

Private _dataItem As Connectivity.DataItem

 

 

Private _values As New Dictionary(Of String, Object)

 

 

Private _originalID As String

 

 

Private _originalVTS As Date

 

 

Private _isNew As Boolean = False

 

 

Private _isModified As Boolean = False

 

 

Private _PropertyCollection As PropertyDescriptorCollection = New PropertyDescriptorCollection(Nothing)

 

#End

 

Region

 

#Region

 

"Constractor"

 

 

Public Sub New(ByRef DataItem As esmOPM.Connectivity.DataItem, ByVal fetchLevel As esmOPM.FetchLevel, ByVal entityDataRow As DataRow)

 

    _dataItem = DataItem

 

    If IsNothing(entityDataRow) Then

 

        _isNew =

True

 

 

        ' create empty dictionary

 

 

        For Each sf In _dataItem.Fields(fetchLevel)

 

            _values.Add(sf.ColumnName,

Nothing)

 

            _PropertyCollection.Add(

New ColumnPropertyDescriptor(sf))

 

 

    Next sf

 

 

Else

 

        _isNew =

False

 

 

        ' parse row-dara values

 

 

        For Each sf In _dataItem.Fields(fetchLevel)

 

        _values(sf.ColumnName) = entityDataRow(sf.ColumnName)

        _PropertyCollection.Add(

New ColumnPropertyDescriptor(sf))

 

 

    Next

 

    _originalID = entityDataRow(_dataItem.PKFieldName).ToString

    _originalVTS = entityDataRow(_dataItem.VTSFieldName)

 

End If

 

 

End Sub

 

#End

 

Region

 

#Region

 

"Public Data Properties"

 

 

Public Property Field(ByVal columnName As Object) As Object

 

 

Get

 

 

        Return _values(columnName)

 

 

End Get

 

 

Set(ByVal value As Object)

 

    _setFieldValue(columnName, value)

 

End Set

 

 

End Property

 

 

Public ReadOnly Property ID() As String

 

 

Get

 

 

    Return _values(_dataItem.PKFieldName).ToString

 

 

End Get

 

 

End Property

 

 

Public Property IsNew() As Boolean

 

 

Get

 

 

    Return _isNew

 

 

End Get

 

 

Set(ByVal value As Boolean)

 

    _isNew = value

 

End Set

 

 

End Property

 

 

Public Property IsModified() As Boolean

 

 

Get

 

 

    Return _isModified

 

 

End Get

 

 

Set(ByVal value As Boolean)

 

    _isModified = value

 

End Set

 

 

End Property

 

#End

 

Region

 

#Region

 

"Internal Properties"

 

 

Friend ReadOnly Property Original_ID() As String

 

 

Get

 

 

    Return _originalID

 

 

End Get

 

 

End Property

 

 

Friend ReadOnly Property Original_VTS() As Date

 

 

Get

 

 

    Return _originalVTS

 

 

End Get

 

 

End Property

 

#End

 

Region

 

#Region

 

"Public Methods"

 

 

Public Sub ParseValues(ByVal valuesDisctionary As Dictionary(Of String, Object))

 

 

    For Each de In valuesDisctionary

 

 

        Me.Field(de.Key) = de.Value

 

 

    Next de

 

 

End Sub

 

 

 

#End

 

Region

 

#Region

 

"Private Methods"

 

 

Private Sub _setFieldValue(ByVal columnName As String, ByVal value As Object)

 

 

        ' store old values

 

 

        If Not (_isNew) AndAlso columnName = _dataItem.PKFieldName Then

 

        _originalID =

Me.Field(columnName).ToString

 

 

        End If

 

 

        If Not (_isNew) AndAlso columnName = _dataItem.VTSFieldName Then

 

        _originalVTS =

CDate(Me.Field(columnName))

 

 

        End If

 

 

        ' set current value

 

    _values(columnName) = value

 

    ' mark this object as being modified

 

    _isModified =

True

 

 

    ' set new timestamp value

 

    _values(_dataItem.VTSFieldName) = Now()

 

End Sub

 

 #End

 

Region

 

 

Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes

 

 

    Return New System.ComponentModel.AttributeCollection(Nothing)

 

 

End Function

 

 

Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName

 

 

    Return Nothing

 

 

End Function

 

 

Public Function GetComponentName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName

 

 

    Return Nothing

 

 

End Function

 

 

Public Function GetConverter() As System.ComponentModel.TypeConverter Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter

 

 

    Return Nothing

 

 

End Function

 

 

Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent

 

 

    Return Nothing

 

 

End Function

 

 

Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty

 

 

    Return Nothing

 

 

End Function

 

 

Public Function GetEditor(ByVal editorBaseType As System.Type) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor

 

 

    Return Nothing

 

 

End Function

 

 

Public Function GetEvents() As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents

 

 

    Return New EventDescriptorCollection(Nothing)

 

 

End Function

 

 

Public Function GetEvents(ByVal attributes() As System.Attribute) As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents

 

 

    Return New EventDescriptorCollection(Nothing)

 

 

End Function

 

 

Public Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties

 

 

    Return _PropertyCollection

 

 

End Function

 

 

Public Function GetProperties(ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties

 

 

    Return _PropertyCollection

 

 

End Function

 

 

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

 

 

    Return Me

 

 

End Function

 

End

 

Class

and finally ... FactoryList Class:

 

Imports

 

System.ComponentModel

 

 

 

Imports

 

esmOPM.Connectivity

 

 

 

Public

 

Class esmList(Of Tkey)

 

 

    Inherits BindingList(Of Tkey)

 

 

    Implements ITypedList

 

 

 

 

#Region

 

"Data Members"

 

 

 

 

 

Private _PropertyCollection As PropertyDescriptorCollection = New PropertyDescriptorCollection(Nothing)

 

 

 

#End

 

Region

 

#Region

 

"Properties"

 

 

 

 

 

Friend WriteOnly Property Fields() As List(Of SystemField)

 

 

Set(ByVal value As List(Of SystemField))

 

 

 

End Set

 

 

 

 

 

End Property

 

#End

 

Region

 

#Region

 

"Constractors"

 

 

 

 

 

 

Public Sub New(ByVal fields As List(Of SystemField))

 

 

    MyBase.New()

 

 

    ' init propertyCollection

 

 

 

 

    _PropertyCollection.Clear()

 

    For Each sf In fields

 

        _PropertyCollection.Add(

New ColumnPropertyDescriptor(sf))

 

 

    Next sf

 

 

End Sub

 

#End

 

Region

 

 

 

 

 

Public Function GetItemProperties(ByVal listAccessors() As System.ComponentModel.PropertyDescriptor) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ITypedList.GetItemProperties

 

 

    Return _PropertyCollection

 

 

End Function

 

 

 

 

 

Public Function GetListName(ByVal listAccessors() As System.ComponentModel.PropertyDescriptor) As String Implements System.ComponentModel.ITypedList.GetListName

 

 

    Return "DefaultView"

 

 

 

 

 

 

 

 

End Function

 

 

 

 

 

 

 

 

End

 

Class

 

1 Answer, 1 is accepted

Sort by
0
Accepted
Mira
Telerik team
answered on 29 Oct 2009, 02:46 PM
Hello Avi,

Please take a look at the Various DataSources demo of the RadGrid showing how to bind the grid to custom collections with sorting enabled. Another option is to implement custom sorting.

If the described issue persists, please open a formal support ticket and attach a sample project replicating the error. We will debug it locally and get back to you with our findings.

Sincerely yours,
Mira
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Tags
Grid
Asked by
Avidan
Top achievements
Rank 1
Answers by
Mira
Telerik team
Share this question
or