Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the CollectionView that is defined in XAML

I wanted to bind to an ObservableCollection in XAML and also apply the grouping there. In principle, this worked fine.

<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>

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

At first, everything seemed cool, until I wanted to refresh the UI from the view model. The problem is, that CollectionViewSource.GetDefaultView(TestTemplates) returned a different view than the one from XAML where the grouping was applied. Thus, I could not set selection or do anything useful with it.

I could fix it by binding the list again directly to the view model's property and setting up the grouping in the code-behind. But I'm not that happy with this solution.

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 assume, the reason for that is already given by John Skeet here.

Nevertheless, I would expect that there should be a way to get the right view. Am I wrong?

like image 992
primfaktor Avatar asked Jun 15 '12 07:06

primfaktor


People also ask

What is ICollectionView?

ICollectionView will give you the ability to filter, sort, or group the collection in addition to propogating INotifyCollectionChanged events if the underlying collection implements it.

What is WPF CollectionViewSource?

CollectionViewSource is a proxy for a CollectionView class, or a class derived from CollectionView. CollectionViewSource enables XAML code to set the commonly used CollectionView properties, passing these settings to the underlying view.

What is ICollectionView in C#?

ICollectionViews are used for filtering, sorting, grouping and also selecting items in list controls (selecting applies only for controls that inherit from the Selector base class such as ListBox, ComboBox etc..).


3 Answers

You could not just do that?

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

If the data is connected, I assume that will have an updated view.

like image 141
J. Lennon Avatar answered Sep 24 '22 04:09

J. Lennon


I tend to just expose the collection view from the VM rather than have the view define it:

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

public ICollectionView EmployeesView
{
    get { ... }
}

That way your VM has full control over what is exposed to the view. It can, for example, change the sort order in response to some user action.

like image 20
Kent Boogaart Avatar answered Sep 21 '22 04:09

Kent Boogaart


Found a way, based on J. Lennon's answer. If I pass something that has access to the resources with my command, then I can look up the CollectionViewSource there.

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();
}

The Execute is the one that is given to the RelayCommand.

This would answer the question, but I don't like it very much. Opinions?

like image 22
primfaktor Avatar answered Sep 23 '22 04:09

primfaktor