WPF provides a simple mechanism for shaping collections of data, via the ICollectionView interface and its Filter, SortDescriptions and GroupDescriptions properties:

// Collection to which the view is bound
public ObservableCollection People { get; private set; }
...
// Default view of the People collection
ICollectionView view = CollectionViewSource.GetDefaultView(People);
// Show only adults
view.Filter = o => ((Person)o).Age >= 18;
// Sort by last name and first name
view.SortDescriptions.Add(new SortDescription("LastName", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("FirstName", ListSortDirection.Ascending));
// Group by country
view.GroupDescriptions.Add(new PropertyGroupDescription("Country"));

Even though this technique is not difficult to use, it has a few drawbacks:

The syntax is a bit clumsy and unnatural: the fact that the filter parameter is an object whereas we know it’s actually of type Person makes the code less readable because of the cast, and the specification of the sort and group descriptions is a little repetitive

Specifying the property names as strings introduces a risk of error, since they’re not verified by the compiler

In the last few years, we got used to use Linq to do this kind of things… it would be nice to be able to do the same for the shaping of an ICollectionView.

Let’s see what syntax we could use to do it with Linq… something like this perhaps?

The ShapeView method returns a wrapper which encapsulates the default view of the collection, and exposes Where, OrderBy and GroupBy methods with appropriate signatures to specify the shaping of the CollectionView. Creating the query has no direct effect, the changes are only applied to the view when Apply is called: that’s because it’s better to apply all changes at the same time, using ICollectionView.DeferRefresh, to avoid causing a refresh of the view for each clause of the query. When Apply is called, we can see that the view is correctly updated to reflect the query.

This solution allows to define the filter, sort and grouping in a strongly-typed way, which implies that the code is verified by the compiler. It’s also more concise and readable than the original code… Just be careful with one thing: some queries that are correct from the compiler’s point of view won’t be applicable to a CollectionView. For instance, if you try to group the data by the first letter of the last name (p.LastName.Substring(0, 1)), the GroupBy method will fail because only properties are supported by PropertyGroupDescription.

Note that the wrapper won’t overwrite the shaping properties of the CollectionView if you don’t specify the corresponding Linq clause, so you can just modify the current view without specifying everything again. If you need to clear the properties, you can use the ClearFilter, ClearSort and ClearGrouping methods: