Windows Phone: Live shaping (Live Filtering, Grouping and Sorting of Collections)
Join the DZone community and get the full member experience.
Join For FreeIn WPF 4.5 as in WPF 4.0 the grouping, sorting and filtering operations are done when the item is added to the collection or when the Refresh method is called. The drawback is that if an item property value involved in one of these operations is updated, then the sorting/grouping/filtering will not be done again.
WPF 4.5 introduce a feature called live shaping which shapes the collection view in live. Let’s dig a little more this feature.
This post is the tenth part of a serie on the WPF 4.5 new features.
Basic behavior
When you use a collection in WPF, it’s in fact its default view which is used by the controls. You should read Bea Stollnitz’s post on this feature if you want more information.
You can retrieve the default view on the collection by using the CollectionViewSource static method named GetDefaultView:
var collectionView = CollectionViewSource.GetDefaultView(Persons) as ICollectionView;
The ICollectionView interface exposes methods which enable grouping and sorting described via the GroupDescriptions and SortDescriptions collection respectively. The grouping can then be used in ItemsControl by setting the GroupStyle property. In the snippet below, the persons are sorted and grouped by age:
//Group by age collectionView.GroupDescriptions.Add(new PropertyGroupDescription("Age")); //sort by age collectionView.SortDescriptions.Add(new SortDescription("Age", ListSortDirection.Ascending));
Also, a predicate can be defined to tells if an item is exposed or not by the view on the collection. In this example we do not expose children(under 18):
private void ApplyFilter(ICollectionView collectionView) { //Apply the filter collectionView.Filter = IsPersonAccepted; } //Children are not accepted public bool IsPersonAccepted(object item) { Person p = item as Person; return (p != null) && p.Age > 18; }
The items are filtered, sorted and grouped on two occasions:
- When they are added to the collection which is the source of the view.
- When you call the Refresh method on a view.
This is fine but it does not cover every possible scenario. For example, if an item update the value of the property on which one of this operation is done, no refreshing is done.
To illustrate this, I created a little demo which groups and sort a
collection of persons by age and removes the one under 18. It can be
found on my Dropbox folder after registration.
A button, changes randomly the age of the persons. An another adds one
year to each of the persons of the collection. After several click on
those buttons, it ends up with a list displaying strange things: the
groups are no more representative and the persons are no more sorted.
More over, there is children(under 18) who are displayed and some who
are not :
This can be a wanted feature as you may want the collection display to be updated in live. If so, the live shaping is here for you in WPF 4.5 !
Live shaping
This new feature is an opt-in one. You can activate live sorting, live grouping and live filtering separately and by default each is disabled.
The ICollectionView interface is still the same and nothing more is exposed. However you have to use a new interface named ICollectionViewLiveShaping.
There is three properties relative to each operation (grouping, sorting, filtering):
- A boolean CanChangeLiveXXX telling if the live shaping for the operation XXX can be activated. It is read-only. BindingListCollectionView and ListCollectionView always returns true at this time.
- A null-able boolean IsLiveXXX telling if the live shaping for the operation XXX is activated.
- A collection of strings LiveXXXProperties containing the names of the property on the view’s item regarding to the operation.
The most important one is maybe the last. When you define a sorting, a
grouping or a filter, some property of the contained items are
involved. By adding a property name in the LiveXXXProperties collection
you tell the framework: on each change of the property with this name, you have to refresh the operation XXX.
As you can have guessed, it works using the INotifyPropertyChanged
interface. The collection view register to each of the item added to the
collection and listen for changes at the aimed properties. Simple as
that !
The process to activate one operation is this one:
- Be sure that the aimed item implement INotifyPropertyChanged;
- Retrieve the ICollectionViewLiveShaping;
- Check if the operation XXX can be activated;
- Add the property involved in the XXX operation in the LiveXXXProperties;
- Activate live XXX operation via the IsLiveXXX property.
I created some helpers for the above demo application which activate each of them.
Live sorting
//In a method before ActiveLiveSorting(collectionView, new List<string>("Age"); // ... private void ActiveLiveSorting(ICollectionView collectionView, IList<string> involvedProperties) { var collectionViewLiveShaping = collectionView as ICollectionViewLiveShaping; if (collectionViewLiveShaping == null) return; if (collectionViewLiveShaping.CanChangeLiveSorting) { foreach(string propName in involvedProperties) collectionViewLiveShaping.LiveSortingProperties.Add(propName); collectionViewLiveShaping.IsLiveSorting = true; } }
Live grouping
//In a method before ActiveLiveGrouping(collectionView, new List<string>("Age"); // ... private void ActiveLiveGrouping(ICollectionView collectionView, IList<string> involvedProperties) { var collectionViewLiveShaping = collectionView as ICollectionViewLiveShaping; if (collectionViewLiveShaping == null) return; if (collectionViewLiveShaping.CanChangeLiveGrouping) { foreach(string propName in involvedProperties) collectionViewLiveShaping.LiveGroupingProperties.Add(propName); collectionViewLiveShaping.IsLiveGrouping = true; } }
Live filtering
//In a method before ActiveLiveFiltering(collectionView, new List<string>("Age"); // ... private void ActiveLiveFiltering(ICollectionView collectionView, IList<string> involvedProperties) { var collectionViewLiveShaping = collectionView as ICollectionViewLiveShaping; if (collectionViewLiveShaping == null) return; if (collectionViewLiveShaping.CanChangeLiveFiltering) { foreach(string propName in involvedProperties) collectionViewLiveShaping.LiveFilteringProperties.Add(propName); collectionViewLiveShaping.IsLiveFiltering = true; } }
Then you can play as much as you want with the buttons, the group, sorting and filtering is performed well.
Side notes
I am very excited about this feature but it is a very expensive one so be careful to activate it only if needed and only the one you actually need. It may be a good idea too to de-activate it when it’s no more needed.
Finally, you may find interesting that the ItemsCollection class, which is used to hold the list of items of an ItemControls implement the ICollectionViewLiveShaping interface too.
Opinions expressed by DZone contributors are their own.
Trending
-
Integration Testing Tutorial: A Comprehensive Guide With Examples And Best Practices
-
How To Manage Vulnerabilities in Modern Cloud-Native Applications
-
Using OpenAI Embeddings Search With SingleStoreDB
-
Health Check Response Format for HTTP APIs
Comments