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

[Solved] Adding ColumnFilterDescriptor throws error

12 Answers 408 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Roland
Top achievements
Rank 1
Roland asked on 08 Aug 2011, 07:12 AM
Hi,


I have a GridView bound to a DomainDataSource. In my DomainDataSource, I have a default filter on one of the fields. I want this default filter to show up in the column filter. I try to do this by adding a ColumnFilterDescriptor to my grid after the LoadedData event of the DomainDataSource. However I am getting the following error whenever I add something to the FilterDescriptors collection:


{System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at Telerik.Windows.Controls.Data.DataFilter.CompositeFilterViewModel.FilterViewModelCollection.Add(IEnumerable`1 filterDescriptors)
   at Telerik.Windows.Controls.Data.DataFilter.CompositeFilterViewModel.FilterViewModelCollection..ctor(CompositeFilterViewModel parent)
   at Telerik.Windows.Controls.Data.DataFilter.CompositeFilterViewModel..ctor(ICompositeFilterDescriptor descriptor, IEnumerable`1 itemProperties, Boolean canUserCreateCompositeFilters, Action`1 filterOperatorsLoadingCallback)
   at Telerik.Windows.Controls.Data.DataFilter.FilterViewModel.PrepareCompositeFilter(IFilterDescriptor filterDescriptor)
   at Telerik.Windows.Controls.Data.DataFilter.FilterViewModel.Prepare(IFilterDescriptor filterDescriptor)
   at Telerik.Windows.Controls.Data.DataFilter.FilterViewModel..ctor(IFilterDescriptor filterDescriptor, IEnumerable`1 itemPropertyDefinitions, Boolean canUserCreateCompositeFilters, Action`1 filterOperatorsLoadingCallback)
   at Telerik.Windows.Controls.Data.DataFilter.CompositeFilterViewModel.FilterViewModelCollection.Add(IEnumerable`1 filterDescriptors)
   at Telerik.Windows.Controls.Data.DataFilter.CompositeFilterViewModel.FilterViewModelCollection..ctor(CompositeFilterViewModel parent)
   at Telerik.Windows.Controls.Data.DataFilter.CompositeFilterViewModel..ctor(ICompositeFilterDescriptor descriptor, IEnumerable`1 itemProperties, Boolean canUserCreateCompositeFilters, Action`1 filterOperatorsLoadingCallback)
   at Telerik.Windows.Controls.Data.DataFilter.FilterViewModel.PrepareCompositeFilter(IFilterDescriptor filterDescriptor)
   at Telerik.Windows.Controls.Data.DataFilter.RootFilterViewModel.Prepare(IFilterDescriptor filterDescriptor)
   at Telerik.Windows.Controls.Data.DataFilter.FilterViewModel..ctor(IFilterDescriptor filterDescriptor, IEnumerable`1 itemPropertyDefinitions, Boolean canUserCreateCompositeFilters, Action`1 filterOperatorsLoadingCallback)
   at Telerik.Windows.Controls.Data.DataFilter.RootFilterViewModel..ctor(ICompositeFilterDescriptor compositeFilterDescriptor, IEnumerable`1 itemPropertyDefinitions, Boolean canUserCreateCompositeFilters, Action`1 filterOperatorsLoadingCallback)
   at Telerik.Windows.Controls.RadDataFilter.RefreshViewModel()
   at Telerik.Windows.Controls.RadDataFilter.OnQueryableSourcePropertyChanged(Object sender, PropertyChangedEventArgs e)
   at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
   at Telerik.Windows.Data.DataItemCollection.OnPropertyChanged(PropertyChangedEventArgs e)
   at Telerik.Windows.Data.DataItemCollection.Telerik.Windows.Data.IWeakEventListener<System.ComponentModel.PropertyChangedEventArgs>.ReceiveWeakEvent(Object sender, PropertyChangedEventArgs args)
   at Telerik.Windows.Data.WeakEvent.WeakListener`1.Handler(Object sender, TArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.OnPropertyChanged(PropertyChangedEventArgs e)
   at Telerik.Windows.Data.QueryableCollectionView.OnPropertyChanged(String propertyName)
   at Telerik.Windows.Data.QueryableCollectionView.InvalidateItemProperties()
   at Telerik.Windows.Data.QueryableCollectionView.OnElementTypeChanged()
   at Telerik.Windows.Data.QueryableCollectionView.set_ElementType(Type value)
   at Telerik.Windows.Data.QueryableCollectionView.InitializeElementType()
   at Telerik.Windows.Data.QueryableCollectionView.InvalidateQueryableSourceCollection()
   at Telerik.Windows.Data.QueryableCollectionView.EnsureCorrectQueryableSourceCollection(NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.OnSourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.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.Windows.Controls.DomainDataSourceView.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.DomainDataSourceView.OnCollectionViewCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Controls.EntityCollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.PagedEntityCollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.PagedEntityCollectionView.CompletePageMove(Int32 pageIndex)
   at System.Windows.Controls.PagedEntityCollectionView.<.ctor>b__0(Object sender, EventArgs args)
   at System.Windows.Controls.PagedEntityCollection.NotifyPageChanged(Int32 startPageIndex, Int32 pageIndex)
   at System.Windows.Controls.DomainDataSource.RaisePageChanged(LoadContext loadContext, Int32 newStartPageIndex, Int32 newPageIndex)
   at System.Windows.Controls.DomainDataSource.DomainContext_Loaded(LoadedDataEventArgs e, LoadContext loadContext)
   at System.Windows.Controls.DomainDataSource.LoadData_Callback(LoadOperation loadOperation)
   at System.ServiceModel.DomainServices.Client.LoadOperation.<>c__DisplayClass4`1.<Create>b__0(LoadOperation`1 arg)
   at System.ServiceModel.DomainServices.Client.LoadOperation`1.InvokeCompleteAction()
   at System.ServiceModel.DomainServices.Client.OperationBase.Complete(Object result)
   at System.ServiceModel.DomainServices.Client.LoadOperation.Complete(DomainClientResult result)
   at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult asyncResult)
   at System.ServiceModel.DomainServices.Client.DomainContext.<>c__DisplayClass1b.<Load>b__17(Object )}


Here is my code for adding the filter:


var defaultDateFilter = new ColumnFilterDescriptor((IDataFieldDescriptor)LogGridView.Columns["Timestamp"]);
defaultDateFilter.FieldFilter.Filter1.Operator = Telerik.Windows.Data.FilterOperator.IsGreaterThanOrEqualTo;
defaultDateFilter.FieldFilter.Filter1.Value = DateTime.UtcNow.Date.AddDays(-1);
defaultDateFilter.FieldFilter.Filter1.Member = "Timestamp";
defaultDateFilter.FieldFilter.Filter1.MemberType = typeof(DateTime);
_gridView.FilterDescriptors.Add(defaultDateFilter);

12 Answers, 1 is accepted

Sort by
0
Rossen Hristov
Telerik team
answered on 08 Aug 2011, 01:08 PM
Hello Roland,

From the stack trace it is clear that you have a RadDataFilter in the whole picture as well.

We have fixed a bug that caused a similar exception recently. Could you please try to upgrade your project to our Latest Internal Build, which will be released later today and see whether the exception will go away.

Also, how have you connected RadDataFilter to RadGridView? Have in mind that if you want to use RadDataFilter to filter RadGridView, you will have to disable RadGridView's built-in filtering (the funnels) as described in our documentation. In other words, RadGridView's default built-in filtering (the funnels) cannot co-exist with RadDataFilter. You have to choose either one or the other. But not both.

In case the problem persists after you upgrade, I would like to ask you to attach a runnable sample project that reproduces this exception. You might want to download our Latest Internal Build in order to be able to attach files here.

Greetings,
Ross
the Telerik team

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

0
Roland
Top achievements
Rank 1
answered on 10 Aug 2011, 02:33 AM
Hi Ross,

Thanks for the answers.

For my case I only use the RadDataFilter to filter against the row details, so grid columns are not filterable in the RadDataFilter. Will this still cause the issue you mentioned?
Here is the xaml connecting the RadDataFilter and RadGridView:

<telerik:RadDataFilter x:Name="MessageFilter" Source="{Binding Items, ElementName=LogGridView}" Grid.Row="1"
                                           AutoGenerateItemPropertyDefinitions="False" CanUserCreateCompositeFilters="False">
                        <telerik:RadDataFilter.ItemPropertyDefinitions>
                            <datafilter:ItemPropertyDefinition PropertyName="FormattedMessage"
                                                               PropertyType="{Binding String, Source={StaticResource Types}}" DisplayName="Formatted Message"/>
                        </telerik:RadDataFilter.ItemPropertyDefinitions>
                    </telerik:RadDataFilter>
                    <telerik:RadGridView x:Name="LogGridView" Grid.Row="2" ItemsSource="{Binding Path=DataSource.Data}"
                                         CanUserDeleteRows="False" CanUserInsertRows="False" AutoGenerateColumns="False" IsReadOnly="True"
                                         Sorting="LogGridView_Sorting" Filtering="LogGridView_Filtering" DistinctValuesLoading="LogGridView_DistinctValuesLoading">
....

Where can I get the Latest Internal Build?

Thank you,
Roland
0
Rossen Hristov
Telerik team
answered on 10 Aug 2011, 08:29 AM
Hi Roland,

Home -> Your Account -> Your Products -> Latest Internal Builds.

Try here.

Regards,
Ross
the Telerik team

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

0
Roland
Top achievements
Rank 1
answered on 11 Aug 2011, 03:47 AM
Hi Ross,

I've finally managed to use the binaries from the link you provided. The issue in adding ColumnFilterDescriptors seems to have been fixed. However, I'm now getting some incorrect behavior with the RadDataFilter. The conditions in the filter seem to be created 4 times on initial load, and clearing them would clear the default column filters.

You mentioned that I should not use the RadDataFilter with the Column Auto Filters. Can you tell me what the recommended approach is to filter the Row Details? For my case, the row detail is just a string property on the same Entity bound to the master row.

Please note that our users prefer to have the Column Auto Filters as it is a more familiar experience from them

Thanks,
Roland
0
Rossen Hristov
Telerik team
answered on 11 Aug 2011, 08:20 AM
Hi Roland,

I think that I have managed to explain this, but I will try again.

When RadGridView and RadDataFilter "detect" each other they will automatically start synchronizing their descriptors. That is the main reason why you should not use both RadDataFilter and RadGridView's column filters. Think about this -- in RadDataFilter you can create a composite filter that could be infinitely nested and complex. RadGridView cannot show this condition in its fixed predefined UI. That is why you have to chose either RadDataFilter or RadGridView's built in column filters, but never both. That is described in the documentation. My suggestion in your particular case would be to lose RadDataFilter and use RadGridView's built-in column filters.

I hope this helps.

Kind regards,
Ross
the Telerik team

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

0
Roland
Top achievements
Rank 1
answered on 11 Aug 2011, 08:50 AM
Hi Ross,

That part, I actually already got. Maybe the answer to this is obvious, but my question now, is how would I be able to filter the RowDetails without the use of RadDataFilter. Please note that I am using a GridViewToggleRowDetailsColumn, and ideally I would like a ColumnFilter (funnel) in that, (but any other way to filter the RowDetails will be fine too).

Please note that my RowDetails is a simple string (very long string) Property in my Entity.

Thanks
0
Rossen Hristov
Telerik team
answered on 11 Aug 2011, 09:26 AM
Hi Roland,

I am not sure how Row Details can be a string. Row Details is the area beneath each row in which you can display any property from the master data item. So I am totally confused now.

I have attached a very simple project which uses the row details feature. We have Clubs in the master grid and the Club's Players in the Row Details grid. The DataContext of the row details element is in fact the parent row's data item (Club) and you can bind anything that is inside the row details to this parent data item's properties. This is described in our documentation.

So after having established what row details are, can you please explain in greater detail how do you want to filer the Players that are inside the row details of every single row containing a Club from the master grid. You can provide an concrete example with my sample project, if that will makes things clear.

I am looking forward to hearing from you.

Regards,
Ross
the Telerik team

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

0
Roland
Top achievements
Rank 1
answered on 11 Aug 2011, 09:49 AM
Hi Ross,

Apologies for the lack of details. I will try to include as much information as I can here.

I realize that the usage of Row Details are usually for displaying related details/entities(to the master row), and usually in a child grid; but for my case, I only use the Row Details area to display another string property belonging to the master row.  The reason for this is that this property can be a very long string, hence displaying it as another column will not be pretty.

To give you an idea, here is a sample xaml of what I am doing:

<telerik:RadGridView x:Name="GridView" Grid.Row="2" ItemsSource="{Binding Path=DataSource.Data}"
                                         CanUserDeleteRows="False" CanUserInsertRows="False" AutoGenerateColumns="False" IsReadOnly="True"
                                         Sorting="GridView_Sorting" Filtering="GridView_Filtering" DistinctValuesLoading="GridView_DistinctValuesLoading">
                        <telerik:RadGridView.Columns>
                            <telerik:GridViewToggleRowDetailsColumn ExpandMode="Multiple" IsFilterable="True" ShowFieldFilters="True"/>
                            <telerik:GridViewDataColumn Header="Category" DataMemberBinding="{Binding Category.Name}"/>
                            <telerik:GridViewDataColumn Header="Machine Name" DataMemberBinding="{Binding MachineName}" ShowDistinctFilters="False"/>
                            <telerik:GridViewDataColumn Header="Process Name" DataMemberBinding="{Binding ProcessName}" TextTrimming="WordEllipsis" MaxWidth="300" ShowDistinctFilters="False"/>
                            <telerik:GridViewDataColumn Header="Timestamp" DataMemberBinding="{Binding Timestamp}" ShowDistinctFilters="False"/>
			    <!-- More columns omitted -->																										
                        </telerik:RadGridView.Columns>
                        <telerik:RadGridView.RowDetailsTemplate>
                            <DataTemplate>
                                <telerik:GroupBox Margin="10,0,10,5" Header="Long Message">
                                    <TextBlock Text="{Binding LongMessage}" Margin="10"/>
                                </telerik:GroupBox>
                            </DataTemplate>
                        </telerik:RadGridView.RowDetailsTemplate>
                    </telerik:RadGridView>

Notice that in the RowDetailsTemplate, I am simply binding to another string property in my master row's ViewModel. So for my case, I only want to filter against the 'LongMessage' property in my master row view model. Previously, I did this by adding a RadDataFilter with only the LongMessage property defined in the ItemPropertyDefinitions. Now I'm looking for an alternative approach to achieve the same result.

Note that my scenario is different from your example(and typical scenarios), as I don't bind to another object for my Row Details. 

Hope this clears my situation.
Thanks,
Roland
0
Accepted
Rossen Hristov
Telerik team
answered on 11 Aug 2011, 11:42 AM
Hello Roland,

Now I see what you mean.

I have prepared a sample project that demonstrates how to achieve this type of architecture. The important thing to note in this project is that I have bound RadDataFilter to the source collection and then I have bound RadGridView to the FilteredSource property of the RadDataFilter. This ensures the following data flow:

source collection (all data) -> RadDataFilter -> (what's left after RadDataFilter has filtered it) -> RadGridView.

The other important thing to note in the project is that I have set the DescriptorSynchronizationMode to None. This will prevent RadGridView from synchronizing its FilterDescriptors back to RadDataFilter when the user filters RadGridView through its column filters (the funnels).

My project uses the Latest Internal Build version which is required for this to work.

I hope this helps.

Best wishes,
Ross
the Telerik team

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

0
Roland
Top achievements
Rank 1
answered on 12 Aug 2011, 09:22 AM
Thanks Ross!

This works. The only other thing I had to do was use RadDomainDataSource as I was also using a RadDataPager. Without RadDomainDataSource, I couldn't get the RadDataPager to bind to the FilteredSource, causing some pages to have an items count less than the pagesize.  

For future reference, the solution is to:

- use latest Telerik Internal Build binaries to fix the original issue (adding ColumnFilterDescriptor throws error)
- Bind the RadDataFilter to the RadDomainDataSource.DataView
- Bind the RadGridView to the RadDataFilter.FilteredSource
- Bind the RadDataPager to the RadDomainDataSource.DataView
- Set the RadGridView.Items.DescriptorsSynchronizationMode = SynchronizationMode.None
- Update the RadDomainDataSource FilterDescriptors when the RadGridView Filtering event fires (as per RadGridView demo)

The only issue I have now is when selecting more than one DistinctValue is selected for a column, the filters created do not result with the correct operator (OR).

Also I'm curious to know why the Demo does not make use of the RadDomainDataSource. If I understood correctly, Composite filters are supported by RadDomainDataSource.
0
Rossen Hristov
Telerik team
answered on 12 Aug 2011, 11:17 AM
Hello Roland,

If you bind RadGridView directly to RadDomainDataSource it will start filtering on the server automatically. You will not have to capture the Filtered event and transfer FilterDescriptors by hand. But I guess that is not an option, since you have wired RadGridView behind RadDataFilter.FilteredSource.

You can change the operator of RadDomainDataSource.FilterDescriptors collection by assigning its LogicalOperator property to OR. 

I believe that you might find might blog posts about RadDomainDataSource interesting:

I hope this helps.Best wishes,
Ross
the Telerik team

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

0
Roland
Top achievements
Rank 1
answered on 12 Aug 2011, 11:24 AM
Thanks Ross. I will surely check these articles out. 

I actually went with a completely different approach, since it got painfully messy using the RadDataFilter and GridView filters with RIA. I ended up removing the RadDataFilter altogether and use the built-in filtering of the RadGridView with RadDomainDataSource.

For my details filtering, I removed the GridViewToggleDetailsColumn and then bound the LongMessage property to a column whose CellTemplate contains only a togglebutton.  This in effect gives the column filter on my pseudo toggle details column. From there I just changed the DetailsVisibility based on the toggle button's status. This seems to be working well and much cleaner in fact.
Tags
GridView
Asked by
Roland
Top achievements
Rank 1
Answers by
Rossen Hristov
Telerik team
Roland
Top achievements
Rank 1
Share this question
or