I'm currently implementing a complex filter for handling a column bound to a collection item, and I'm having trouble creating a lambda expression that will work with the Telerik filters.
The collection item I am binding to is itself a Collection, and also has 2 properties- DistrictNo and ParentDistrictNo. The lambda expression I am creating works out to
{item => ((item.StoreTeams.Item[212].Employees.ParentDistrictNo == 0) And (item.StoreTeams.Item[212].Employees.DistrictNo == 0))}
where "item" is the object bound to the row (SCTMStore). This compiles fine, but when it gets to adding my custom filter descriptor to the gridview's filterdescriptor's collection, I get this error (at the end of the message)
Is there any reason why a lambda expression can't be handled by the telerik filter components?
Here's the CreateFilterExpression I'm overriding to create the expression (the code in question is in the "unassigned" if block)-
Public Function CreateFilterExpression(instance As System.Linq.Expressions.Expression) As Expression Implements Telerik.Windows.Data.IFilterDescriptor.CreateFilterExpression
' Need to build the linq expression by each individual dereference
Dim propertyName = Me.m_column.DataMemberBinding.Path.Path.Substring(0, Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("["))
Dim iIndex = CInt(Me.m_column.DataMemberBinding.Path.Path.Substring(Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("[") + 1, Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("]") - (Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("[") + 1)))
Dim GenericContainsMethod As MethodInfo = GetMethodInfo(Me.FilterOperator, "test")
Dim GenericAnyMethod As MethodInfo = GetAnyMethodInfo(Me.FilterOperator, Me.Value)
' item.StoreTeams
Dim collectionPropertyAccessor = Expression.Property(instance, propertyName)
' item.StoreTeams.Item(x)
Dim ItemcollectionPropertyAccessor = Expression.Property(collectionPropertyAccessor, "Item", Expression.Constant(iIndex))
' item.StoreTeams.Item(x).Employees
Dim EmployeeNosPropertyAccessor = Expression.Property(ItemcollectionPropertyAccessor, "Employees")
If Me.Value = "unassigned" Then
Dim collectionPropertyAccessor2 = Expression.Property(instance, propertyName)
Dim ItemcollectionPropertyAccessor2 = Expression.Property(collectionPropertyAccessor2, "Item", Expression.Constant(iIndex))
Dim EmployeeNosPropertyAccessor2 = Expression.Property(ItemcollectionPropertyAccessor2, "Employees")
Dim ParentDistrictNoAccessor As Expression = Expression.Property(EmployeeNosPropertyAccessor2, "ParentDistrictNo")
Dim DistrictNoAccessor As Expression = Expression.Property(EmployeeNosPropertyAccessor2, "DistrictNo")
Dim ParentDistrictNoComparer As Expression = Expression.Equal(ParentDistrictNoAccessor, Expression.Constant(0))
Dim DistrictNoComparer As Expression = Expression.Equal(DistrictNoAccessor, Expression.Constant(0))
Dim AndComparer As Expression = Expression.And(ParentDistrictNoComparer, DistrictNoComparer)
Dim returnresult As Expression = Expression.Lambda(Of Func(Of BusinessObjects.SCTMStore, Boolean))(AndComparer, DirectCast(instance, ParameterExpression))
Return returnresult
End If
' item.StoreTeams.Item(x).Employees.Items
Dim ItemsPropertyAccessor = Expression.Property(EmployeeNosPropertyAccessor, "Items")
If Me.Value = "unstaffed" Then
' item.StoreTeams.Item(x).Employees.Items.Any()
Dim testresult As Expression = Expression.Call(GenericAnyMethod, ItemsPropertyAccessor)
' !item.StoreTeams.Item(x).Employees.Items.Any()
Return Expression.[Not](testresult)
End If
' item.StoreTeams.items.Item(x).Employees.Items.Cast<object>().Contains("the value")
Dim genericCollectionPropertyAccessor = Expression.Call(Nothing, EnumerableCastMethod.MakeGenericMethod(GetType(String)), ItemsPropertyAccessor)
Dim result As Expression = Expression.Call(GenericContainsMethod, genericCollectionPropertyAccessor, Expression.Constant(Me.Value))
If Me.FilterOperator = FilterOperator.DoesNotContain Then
'!item.StoreTeams.Item(x).Employees.Items.Cast<object>().Contains("the value")
result = Expression.[Not](result)
End If
Return result
End Function
- Jay
===================================================================================
System.ArgumentException occurred
Message=The value "((RAMWare.Controls.ContactManagement.CollectionFilterDescriptor))" is not of type "Telerik.Windows.Data.IFilterDescriptor" and cannot be used in this generic collection.
Parameter name: value
StackTrace:
at System.ThrowHelper.ThrowWrongValueTypeArgumentException(Object value, Type targetType)
at System.Collections.ObjectModel.Collection`1.System.Collections.IList.Insert(Int32 index, Object value)
at Telerik.Windows.Data.CollectionHelper.Insert(IList target, IEnumerable newItems, Int32 startingIndex, IEqualityComparer itemComparer)
at Telerik.Windows.Data.ObservableCollectionManager.HandleCollectionChanged(IList sender, NotifyCollectionChangedEventArgs args)
at Telerik.Windows.Data.ObservableCollectionManager.Telerik.Windows.Data.IWeakEventListener<System.Collections.Specialized.NotifyCollectionChangedEventArgs>.ReceiveWeakEvent(Object sender, NotifyCollectionChangedEventArgs args)
at Telerik.Windows.Data.WeakEvent.WeakListener`1.Handler(Object sender, TArgs args)
at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at Telerik.Windows.Data.RadObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at Telerik.Windows.Data.ObservableItemCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at Telerik.Windows.Data.RadObservableCollection`1.InsertItem(Int32 index, T item)
at Telerik.Windows.Data.FilterDescriptorCollection.InsertItem(Int32 index, IFilterDescriptor item)
at System.Collections.ObjectModel.Collection`1.Add(T item)
at RAMWare.Controls.ContactManagement.EmployeeCollectionFilterControl.PART_DistinctValuesList_SelectionChanged(Object sender, SelectionChangedEventArgs e)
InnerException:
===================================================================================
The collection item I am binding to is itself a Collection, and also has 2 properties- DistrictNo and ParentDistrictNo. The lambda expression I am creating works out to
{item => ((item.StoreTeams.Item[212].Employees.ParentDistrictNo == 0) And (item.StoreTeams.Item[212].Employees.DistrictNo == 0))}
where "item" is the object bound to the row (SCTMStore). This compiles fine, but when it gets to adding my custom filter descriptor to the gridview's filterdescriptor's collection, I get this error (at the end of the message)
Is there any reason why a lambda expression can't be handled by the telerik filter components?
Here's the CreateFilterExpression I'm overriding to create the expression (the code in question is in the "unassigned" if block)-
Public Function CreateFilterExpression(instance As System.Linq.Expressions.Expression) As Expression Implements Telerik.Windows.Data.IFilterDescriptor.CreateFilterExpression
' Need to build the linq expression by each individual dereference
Dim propertyName = Me.m_column.DataMemberBinding.Path.Path.Substring(0, Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("["))
Dim iIndex = CInt(Me.m_column.DataMemberBinding.Path.Path.Substring(Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("[") + 1, Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("]") - (Me.m_column.DataMemberBinding.Path.Path.ToString.IndexOf("[") + 1)))
Dim GenericContainsMethod As MethodInfo = GetMethodInfo(Me.FilterOperator, "test")
Dim GenericAnyMethod As MethodInfo = GetAnyMethodInfo(Me.FilterOperator, Me.Value)
' item.StoreTeams
Dim collectionPropertyAccessor = Expression.Property(instance, propertyName)
' item.StoreTeams.Item(x)
Dim ItemcollectionPropertyAccessor = Expression.Property(collectionPropertyAccessor, "Item", Expression.Constant(iIndex))
' item.StoreTeams.Item(x).Employees
Dim EmployeeNosPropertyAccessor = Expression.Property(ItemcollectionPropertyAccessor, "Employees")
If Me.Value = "unassigned" Then
Dim collectionPropertyAccessor2 = Expression.Property(instance, propertyName)
Dim ItemcollectionPropertyAccessor2 = Expression.Property(collectionPropertyAccessor2, "Item", Expression.Constant(iIndex))
Dim EmployeeNosPropertyAccessor2 = Expression.Property(ItemcollectionPropertyAccessor2, "Employees")
Dim ParentDistrictNoAccessor As Expression = Expression.Property(EmployeeNosPropertyAccessor2, "ParentDistrictNo")
Dim DistrictNoAccessor As Expression = Expression.Property(EmployeeNosPropertyAccessor2, "DistrictNo")
Dim ParentDistrictNoComparer As Expression = Expression.Equal(ParentDistrictNoAccessor, Expression.Constant(0))
Dim DistrictNoComparer As Expression = Expression.Equal(DistrictNoAccessor, Expression.Constant(0))
Dim AndComparer As Expression = Expression.And(ParentDistrictNoComparer, DistrictNoComparer)
Dim returnresult As Expression = Expression.Lambda(Of Func(Of BusinessObjects.SCTMStore, Boolean))(AndComparer, DirectCast(instance, ParameterExpression))
Return returnresult
End If
' item.StoreTeams.Item(x).Employees.Items
Dim ItemsPropertyAccessor = Expression.Property(EmployeeNosPropertyAccessor, "Items")
If Me.Value = "unstaffed" Then
' item.StoreTeams.Item(x).Employees.Items.Any()
Dim testresult As Expression = Expression.Call(GenericAnyMethod, ItemsPropertyAccessor)
' !item.StoreTeams.Item(x).Employees.Items.Any()
Return Expression.[Not](testresult)
End If
' item.StoreTeams.items.Item(x).Employees.Items.Cast<object>().Contains("the value")
Dim genericCollectionPropertyAccessor = Expression.Call(Nothing, EnumerableCastMethod.MakeGenericMethod(GetType(String)), ItemsPropertyAccessor)
Dim result As Expression = Expression.Call(GenericContainsMethod, genericCollectionPropertyAccessor, Expression.Constant(Me.Value))
If Me.FilterOperator = FilterOperator.DoesNotContain Then
'!item.StoreTeams.Item(x).Employees.Items.Cast<object>().Contains("the value")
result = Expression.[Not](result)
End If
Return result
End Function
- Jay
===================================================================================
System.ArgumentException occurred
Message=The value "((RAMWare.Controls.ContactManagement.CollectionFilterDescriptor))" is not of type "Telerik.Windows.Data.IFilterDescriptor" and cannot be used in this generic collection.
Parameter name: value
StackTrace:
at System.ThrowHelper.ThrowWrongValueTypeArgumentException(Object value, Type targetType)
at System.Collections.ObjectModel.Collection`1.System.Collections.IList.Insert(Int32 index, Object value)
at Telerik.Windows.Data.CollectionHelper.Insert(IList target, IEnumerable newItems, Int32 startingIndex, IEqualityComparer itemComparer)
at Telerik.Windows.Data.ObservableCollectionManager.HandleCollectionChanged(IList sender, NotifyCollectionChangedEventArgs args)
at Telerik.Windows.Data.ObservableCollectionManager.Telerik.Windows.Data.IWeakEventListener<System.Collections.Specialized.NotifyCollectionChangedEventArgs>.ReceiveWeakEvent(Object sender, NotifyCollectionChangedEventArgs args)
at Telerik.Windows.Data.WeakEvent.WeakListener`1.Handler(Object sender, TArgs args)
at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at Telerik.Windows.Data.RadObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at Telerik.Windows.Data.ObservableItemCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
at Telerik.Windows.Data.RadObservableCollection`1.InsertItem(Int32 index, T item)
at Telerik.Windows.Data.FilterDescriptorCollection.InsertItem(Int32 index, IFilterDescriptor item)
at System.Collections.ObjectModel.Collection`1.Add(T item)
at RAMWare.Controls.ContactManagement.EmployeeCollectionFilterControl.PART_DistinctValuesList_SelectionChanged(Object sender, SelectionChangedEventArgs e)
InnerException:
===================================================================================