White screen exception on manual adding of filter descriptor

10 posts, 0 answers
  1. Michael MSTG
    Michael MSTG avatar
    46 posts
    Member since:
    Aug 2012

    Posted 04 Jan 2012 Link to this post

    We've been following this pattern for quite a while now and until recently, it had worked flawlessly.
    http://blogs.telerik.com/rossenhristov/posts/09-11-27/pre-filtering-radgridview-for-silverlight.aspx
    http://www.telerik.com/help/silverlight/radgridview-filtering-column-filter-descriptors.html

    Our code is as follows (gridSettings.GridFilterSettings is our own custom collection that we use to track all possible filters):
    'create the telerik filters
                For Each filterSetting As ListPageGridSettings.FilterSetting In gridSettings.GridFilterSettings
                    Dim newFilter As New Telerik.Windows.Data.FilterDescriptor(filterSetting.FilterPropertyPath, filterSetting.FilterOperator, filterSetting.FilterValue)
     
                    'add if this column is on this grid
                    If grd.Columns(filterSetting.FilterColumn) IsNot Nothing Then
                        'add direct to the grid to allow to be cleared
                        Dim columnFilter As New Telerik.Windows.Controls.GridView.ColumnFilterDescriptor(DirectCast(grd.Columns(filterSetting.FilterColumn), Telerik.Windows.Data.IDataFieldDescriptor))
     
                        If filterSetting.IsFilter1 Then
                            columnFilter.FieldFilter.Filter1.Operator = filterSetting.FilterOperator
                            columnFilter.FieldFilter.Filter1.Value = filterSetting.FilterValue
     
                            'now add to grid, DDS
                            addedFilters.Add(newFilter)
                            grd.FilterDescriptors.Add(columnFilter)
                        ElseIf filterSetting.FilterValue IsNot Telerik.Windows.Data.FilterDescriptor.UnsetValue Then
                            columnFilter.FieldFilter.Filter2.Operator = filterSetting.FilterOperator
                            columnFilter.FieldFilter.Filter2.Value = filterSetting.FilterValue
     
                            'now add to grid, DDS
                            addedFilters.Add(newFilter)
                            grd.FilterDescriptors.Add(columnFilter)
                        End If
                    End If
                Next
     
                'fire the filtering event of the grid to load data and apply filters
                If addedFilters.Count > 0 Then
                    grd.OnFiltering(New Telerik.Windows.Controls.GridView.GridViewFilteringEventArgs(addedFilters, New Telerik.Windows.Data.IFilterDescriptor() {}))
                End If

    The filtering event is raised to handle the translation from a grid filter to a DomainDataSource filter.

    Now we receive this white screen exception when implementing the code:
    Error: Unhandled Error in Silverlight Application
    Code: 4004   
    Category: ManagedRuntimeError      
    Message: System.NullReferenceException: Object reference not set to an instance of an object.
       at Telerik.Windows.Data.Expressions.ExpressionFactory.MakeMemberAccess(Expression instance, String memberName, Type memberType)
       at Telerik.Windows.Data.Expressions.PropertyAccessExpressionBuilder.CreateMemberAccessExpressionOverride()
       at Telerik.Windows.Data.Expressions.MemberAccessExpressionBuilderBase.CreateMemberAccessExpression()
       at Telerik.Windows.Data.Expressions.FilterDescriptorExpressionBuilder.CreateMemberExpression()
       at Telerik.Windows.Data.Expressions.FilterDescriptorExpressionBuilder.CreateBodyExpression()
       at Telerik.Windows.Data.FilterDescriptor.CreateFilterExpression(ParameterExpression parameterExpression)
       at Telerik.Windows.Data.FilterDescriptorBase.CreateFilterExpression(Expression instance)
       at Telerik.Windows.Data.Expressions.FilterDescriptorCollectionExpressionBuilder.CreateBodyExpression()
       at Telerik.Windows.Data.CompositeFilterDescriptor.CreateFilterExpression(ParameterExpression parameterExpression)
       at Telerik.Windows.Data.FilterDescriptorBase.CreateFilterExpression(Expression instance)
       at Telerik.Windows.Data.Expressions.FilterDescriptorCollectionExpressionBuilder.CreateBodyExpression()
       at Telerik.Windows.Data.CompositeFilterDescriptor.CreateFilterExpression(ParameterExpression parameterExpression)
       at Telerik.Windows.Data.FilterDescriptorBase.CreateFilterExpression(Expression instance)
       at Telerik.Windows.Data.Expressions.FilterDescriptorCollectionExpressionBuilder.CreateBodyExpression()
       at Telerik.Windows.Data.CompositeFilterDescriptor.CreateFilterExpression(ParameterExpression parameterExpression)
       at Telerik.Windows.Data.FilterDescriptorBase.CreateFilterExpression(Expression instance)
       at Telerik.Windows.Data.CompositeFilterDescriptorCollection.CreateFilterExpression(Expression instance)
       at Telerik.Windows.Data.ICompositeFilterDescriptorExtensions.GetFilterFunction(ICompositeFilterDescriptor filterDescriptors, Type itemType)
       at Telerik.Windows.Data.QueryableCollectionView.InitializeInternalList(IQueryable view)
       at Telerik.Windows.Data.QueryableCollectionView.CreateInternalList()
       at Telerik.Windows.Data.QueryableCollectionView.get_InternalList()
       at Telerik.Windows.Data.QueryableCollectionView.GetEnumerator()
       at Telerik.Windows.Data.DataItemCollection.GetFlatEnumerator()
       at Telerik.Windows.Data.DataItemCollection.GetEnumerator()
       at Telerik.Windows.Controls.GridView.GridViewVirtualizingPanel.EnsureItems()
       at Telerik.Windows.Controls.GridView.GridViewVirtualizingPanel.MeasureOverride(Size constraint)
       at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)    
     
    Source File:
    Line: 59

    I narrowed it down to when the filter descriptor is added to the grid itself.  If I comment out that line, no exception.
    Here is an XML representation example of the columnFilter above:
     {( (Empty) AND (( (MenuLinkCode IsEqualTo DW ) )) )}

    We are using version 2011.3.1116.1040
    Any ideas?
  2. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 05 Jan 2012 Link to this post

    Hello,

    We are in a process of re-writing the entire filtering from scratch.

    From the code you have pasted I see that you are calling the RadGridView.OnFiltering method which should have never been made public in the first place and will not be available in our next version. It is incorrect for someone from the outside to make a control raise its event and that is why we will hide the respective RadGridView methods.

    Now, if you try to explain in short what is the exact goal of your project we might be able to suggest a more suitable way to implement it.

    Programmatic filtering will also contain breaking changes, which were inevitable if we wanted to improve our filtering model. Please, try to summarize what your code should do and we will try to suggest the best way for doing this.

    We are looking forward to hearing from you.

    All the best,
    Ross
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. Michael MSTG
    Michael MSTG avatar
    46 posts
    Member since:
    Aug 2012

    Posted 05 Jan 2012 Link to this post

    What the purpose of this code was for was to restore any filters the user may have set on a previous visit to the page.  It also serves as a means to "pre-filter" the grid as well, which was what led us to follow the patterns off your blog.

    The reason behind using the OnFiltering method however was due to the fact that we implemented our solution using the stock DomainDataSource.  Because of the paging shortcomings of the RadDomainDataSource, that event is what helped us put the filtering on both client and server sides.  To be honest, I was very surprised that method was public but it did exactly what we needed it to do to simulate the user performing the filtering.

    Thank you for your help.
  4. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 05 Jan 2012 Link to this post

    Hi,

    The exception that you are getting indicates that the grid tries to create its filtering expression while the Type of the member to filter on is still unknown. 

    You mentioned that "We've been following this pattern for quite a while now and until recently, it had worked flawlessly."

    Did you change something in your code so you started getting this exception? When did you start getting the exception?

    Could you please send me a very small dummy sample project that reproduces this exact exception so I can debug it in Visual Studio and see what is null and why. This will definitely be the quickest way to resolve the issue instead of trying to guess what might be going on in your project.

    Thanks in advance.

    By the way, what are the paging shortcomings of RadDomainDataSource?

    Kind regards,
    Ross
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  5. Michael MSTG
    Michael MSTG avatar
    46 posts
    Member since:
    Aug 2012

    Posted 05 Jan 2012 Link to this post

    The only thing we've ever done was upgrade the Telerik assemblies.  This code had been stable for over a year at this point and until the previous release (Q2) of this year, that is when the errors began.  I posted a while back ago that we received this very same error on trying to do the same thing on restoring sorting as well and because of time constraints (we simply haven't been able to devote time to creating a "small project" we can send), we simply commented out the code that adds the sort back to the grid.  The same may be true for the filtering aspect.

    Indicating "The exception that you are getting indicates that the grid tries to create its filtering expression while the Type of the member to filter on is still unknown" means the approach on the blog is no longer valid when working with a DomainDataSource since the grid must have the filter descriptor BEFORE the DDS performs its database request.  If we try to add it after the fact, we then are dealing with two database requests and that simply is not a valid approach, especially if we are requesting a large amount of data.  Should the approach then be to force the data type on the column?

    Regarding the RadDomainDataSource, the simple answer is the control doesn't do paging with a specific load size.  If we are dealing with massive transaction tables, not having a load size presents a possible performance issue.
  6. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 05 Jan 2012 Link to this post

    Hi,

    Without having anything that I can run and debug, the only suggestion that I can really make is to manually set data type of the column by hand. In this way it will be known even before the data arrives to the client and the filter's should use this type when creating their lambda expression. Maybe this can help?

    Greetings,
    Ross
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  7. Michael MSTG
    Michael MSTG avatar
    46 posts
    Member since:
    Aug 2012

    Posted 05 Jan 2012 Link to this post

    I'm assuming this approach?  If so, my next question would then be what would happen if we set them all to say, object?  Once the DDS loads the data, will the binding re-establish the correct data type or do I need to be certain of the data type to bind?  I ask because this code is from a base class and not on each silverlight page so knowing ahead of time isn't possible and I'd like to try to avoid having to modify several hundred instances of the grid view.
  8. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 06 Jan 2012 Link to this post

    Hi,

    Setting them to object is like not setting them at all. The LINQ expression that we try to compile will cry out that the type Object does not have a property FirstName, for example. Whereas the Customer type has a FirstName, etc. That's just a dummy example.

    Once the data arrives to the client we will automatically "see" the actual type and update it accordingly. However, my guess is that the filtering fails because you try to do it before the actual type is known, i.e. it is still Object when the filtering tries to kick-off. 

    Kind regards,
    Ross
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  9. Michael MSTG
    Michael MSTG avatar
    46 posts
    Member since:
    Aug 2012

    Posted 06 Jan 2012 Link to this post

    Understood.  We'll use reflection to determine what data type needs to be set so we can "pre-filter" the grid.  What I'm more curious about at this point however is what we might expect when the next version comes out.
  10. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 06 Jan 2012 Link to this post

    Hello,

    Here is what will change in the next version regarding filtering.

    I will paste the Release Notes that I have assembled here directly:

    *****************************

    Filtering Breaking Changes


    In order to enable filtering for our GridViewExpressionColumn, we had to rewrite our entire filtering infrastructure from scratch. We have made as few breaking changes as possible, but some of them were inevitable, for which we would like to apologize. Here is the list of breaking changes that you should be aware of. Do not hesitate to write us if you are having problems with upgrading your project. We will do our best to assist you.


    - The IFilteringControl.Prepare method now expects the more general type GridViewColumn instead of a GridViewBoundColumnBase as its argument. If you were relying on GridViewBoundColumnBase-specific methods or properties you will have to add a check and a cast.
    - The GridViewDistinctValuesLoadingEventArgs.Column property is now of the more general type GridViewColumn. If you were relying on GridViewBoundColumnBase-specific methods or properties you will have to add a check and a cast in your DistinctValuesLoading event handler.
    - The GridViewDataControl.GetDistinctValues family of methods now accept a GridViewColumn instead of an IDataFieldDescriptor as their first parameter.
    - The EditorCreatedEventArgs.Column is now of the more general type GridViewColumn. If you were relying on GridViewBoundColumnBase-specific methods or properties you will have to add a check and a cast in your DistinctValuesLoading event handler.
    - The FilterOperatorsLoadingEventArgs.Column property is now of type GridViewColumn instead of IDataFieldDescriptor. 
    - The ColumnFilterDescriptor class has been made internal. Use the IColumnFilterDescriptor interface instead. It contains all relevant properties and methods.
    - You can't directly instantiate a ColumnFilterDescriptor anymore since the class has been made internal. When you access the GridViewColumn.ColumnFilterDescriptor property, it will be automatically created on demand by the column and you will be given an IColumnFilterDescriptor to work with. For example: IColumnFilterDescriptor cfd = myColumnInstance.ColumnFilterDescriptor;
    - The IColumnFilterDescriptor.Column property is now of type GridViewColumn instead of IDataFieldDescriptor. 
    - The IColumnFilterDescriptor.DistinctFilter property is now of type IDistinctValuesFilterDescriptor instead of DistinctValuesFilterDescriptor.
    - The IColumnFilterDescriptor.FieldFilter property is now of type IFieldFilterDescriptor instead of FieldFilterDescriptor.
    - The DistinctValuesFilterDescriptor class has been made internal. It is not supposed to be used directly from your code. Use the IDistinctValuesFilterDescriptor interface instead.
    - The FieldFilterDescriptor class has been made internal. It is not supposed to be used directly from your code. Use the IFieldFilterDescriptor interface instead.
    - If you were using code from the GridViewCustomSerialization PersistenceFramework example, please update it according to the updated example.
    - The GridViewDataControl.OnFiltering method is marked as obsolete now. It is not supposed to be used directly from your code and will be made internal in a future realease.
    - The GridViewDataControl.OnFiltered method is marked as obsolete now. It is not supposed to be used directly from your code and will be made internal in a future realease.


    Programmatic Filtering Upgrade
    ------------------------------
    Before:
    GridViewColumn ageColumn = this.radGridView.Columns["Age"];
    ColumnFilterDescriptor ageColumnFilter = new ColumnFilterDescriptor(ageColumn);
    // ...
    ageColumnFilter.FieldFilter.Filter1.Operator = FilterOperator.IsLessThan;
    ageColumnFilter.FieldFilter.Filter1.Value = 10;
    // ...
    this.radGridView.FilterDescriptors.Add(ageColumnFilter);


    After:
    GridViewColumn ageColumn = this.radGridView.Columns["Age"];


    // Getting it from the property will create it and associate it with its column automatically.
    IColumnFilterDescriptor ageColumnFilter = ageColumn.ColumnFilterDesriptor;


    ageColumnFilter.SuspendNotifications();

    // ...
    ageColumnFilter.FieldFilter.Filter1.Operator = FilterOperator.IsLessThan;
    ageColumnFilter.FieldFilter.Filter1.Value = 10;
    // ...

    // There is no need to manually add the column filter to this.radGridView.FilterDescriptors
    // When the column filter is activated/deactivated it is automatically added/removed to this collection.
    ageColumnFilter.ResumeNotifications();

    **********************************************

    I hope this helps.

    Greetings,
    Ross
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Back to Top