Search code examples
c#wpfcollectionviewsource

Filter a CollectionViewSource and then sort manually


I have an ObservableCollection<Recipe> which is bound to an ICollectionView. It is possible to filter by my personal predicate implementation. The ICollectionView is bound on a dataGrid.

Now I would like to reorder the list of Recipes after the the collection has been filtered.

A recipe got a property 'Identifier'. If you have typed in exactly the identifier of the recipe, it should be placed on top of the list.

An example:

  • 12345
  • 1234
  • 123

If you type 1234 into the filter, the Recipe with Identifier = 1234 should be placed an top of the list instead of beeing on second place.

public ICollectionView RecipeCollection
{
    get => _RecipeCollection;
    set
    {
        _RecipeCollection = value;
        OnPropertyChanged();
    }
}
private ICollectionView _RecipeCollection;


Recipes = new ObservableCollection<Recipe>(databaseQuery.Result);
RecipeCollection = CollectionViewSource.GetDefaultView(Recipes);
RecipeCollection.Filter = CollectionViewSource_Filter;



private bool CollectionViewSource_Filter(object item)
{
    if (item is Recipe recipe)
    {
        if (string.IsNullOrEmpty(SearchBox.Text))
        {
            return true;
        }

        string filter = SearchBox.Text.ToLower();
        if (recipe.Identifier.ToLower().Contains(filter))
        {
            return true;
        }

        if (!string.IsNullOrEmpty(recipe.Name) && recipe.Name.ToLower().Contains(filter))
        {
            return true;
        }

        if (!string.IsNullOrEmpty(recipe.Description) && recipe.Description.ToLower().Contains(filter))
        {
            return true;
        }
    }

    return false;
}

Solution

  • You could add a SortOrder property to the Recipe class and a new SortDescription(nameof(Recipe.SortOrder), ListSortDirection.Ascending) to the SortDescriptions property of the ICollectionView. You then set the value of the SortOrder property of all Recipe objects according to the sort order you want. This should reorder the list of recipes.

    Depending on your requirements, you may want to use a CollectionViewSource with live sorting enabled: https://wpf.2000things.com/2014/01/16/988-enabling-live-sorting-in-a-collectionviewsource/

    As pointed out by @redcurry, if you use a ListCollectionView, there is a CustomSort property that you can set to an IComparer.