How can I get a CollectionView that is defined in XAML

I wanted to associate with ObservableCollection in XAML, and also apply grouping there. Basically, it worked well.

 <UserControl.Resources> <CollectionViewSource x:Key="cvs" Source="{Binding Path=TestTemplates}"> <CollectionViewSource.SortDescriptions> <scm:SortDescription PropertyName="Title"/> </CollectionViewSource.SortDescriptions> <CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="TestCategory"/> </CollectionViewSource.GroupDescriptions> </CollectionViewSource> </UserControl.Resources> 

The data binding expression then became ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}" instead of ItemsSource="{Binding Path=TestTemplates}" .

At first, everything seemed cool until I wanted to update the user interface from the view model. The problem is that CollectionViewSource.GetDefaultView(TestTemplates) returns a different view than the XAML where the grouping was applied. Thus, I could not make a choice or do anything useful with it.

I could fix this by again linking the list directly to the property of the view model and adjusting the grouping in the code. But I'm not so happy with this decision.

 private void UserControlLoaded(object sender, RoutedEventArgs e) { IEnumerable source = TemplateList.ItemsSource; var cvs = (CollectionView)CollectionViewSource.GetDefaultView(source); if (cvs != null) { cvs.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending)); cvs.GroupDescriptions.Add(new PropertyGroupDescription("TestCategory")); } } 

I guess the reason for this is already pointed out by John Skeet here .

However, I expect that there should be a way to get the right idea. I am wrong?

+8
c # wpf xaml code-behind collectionviewsource
source share
3 answers

Found a method based on J. Lennon . If I pass something that has access to resources using my command, then I can find there CollectionViewSource .

In XAML ( CollectionViewResource as above):

 <Button Command="{Binding Command}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">Do it!</Button> 

And in the VM code:

 private void Execute(object parm) { var fe = (FrameworkElement)parm; var cvs = (CollectionViewSource)fe.FindResource("cvs"); cvs.View.Refresh(); } 

Execute is the one assigned by RelayCommand .

This will answer the question, but I do not really like it. Opinions?

+1
source share

I try to simply expose the collection view from the virtual machine, and not determine its appearance:

 public ICollection<Employee> Employees { get { ... } } public ICollectionView EmployeesView { get { ... } } 

Thus, your virtual machine has full control over what is displayed in the view. He can, for example, change the sort order in response to some user actions.

+5
source share

You could not do it?

 var _viewSource = this.FindResource("cvs") as CollectionViewSource; 

If the data is connected, I assume it will have an updated look.

+5
source share

All Articles