I have implemented a filter for filtering a IEnumerable of a specific type.To accomblish this goal i have created three classes: FilterOption, Filter and the FilterManager.FilterOption.cspublic class FilterOption<TFilterOptionType>{    private bool _isSelected;    public bool IsSelected    {        get { return _isSelected; }        set        {            _isSelected = value;            this.OnIsSelectedChanged(new EventArgs());        }    }    public TFilterOptionType Option { get; private set; }    public FilterOption(TFilterOptionType option)    {        this.Option = option;    }    public event EventHandler IsSelectedChanged;    protected virtual void OnIsSelectedChanged(EventArgs e)    {        IsSelectedChanged?.Invoke(this, e);    }}Filter.cspublic class Filter<TFilterType, TFilterOptionType>{    public bool IsActive => this.Options.Any(option => option.IsSelected);    public string Name { get; private set; }    public ObservableCollection<TFilterType> FilteredItems{ get; }    public List<FilterOption<TFilterOptionType>> Options { get; set; }    private Func<TFilterType, TFilterOptionType> PropertyGetter { get; }    public Filter(        string name,        IEnumerable<TFilterType> items,        ObservableCollection<TFilterType> filteredItems,        Func<TFilterType, TFilterOptionType> propertyGetter)    {        this.Name = name;        this.FilteredItems = filteredItems;        this.PropertyGetter = propertyGetter;        this.Options =            items.Select(x => this.PropertyGetter(x))                .Distinct()                .OrderBy(option => option)                .Select(option => new FilterOption<TFilterOptionType>(option))                .ToList();    }    public void Refresh()    {        if (this.IsActive)        {            foreach (var option in this.Options.Where(option => !option.IsSelected))            {                this.FilteredItems.RemoveAll(item => this.PropertyGetter(item).Equals(option.Option));            }        }    }}FilterManager.cspublic class FilterManager<TFilterType>{    public ObservableCollection<Filter<TFilterType, IComparable>> Filters { get; set; } =        new ObservableCollection<Filter<TFilterType, IComparable>>();    public ObservableCollection<TFilterType> FilteredItems { get; } = new ObservableCollection<TFilterType>();    private IEnumerable<TFilterType> Items { get; }    public FilterManager(IEnumerable<TFilterType> items)    {        this.Items = items;        this.FilteredItems.Add(this.Items);    }    public void AddFilter(string filterName, Func<TFilterType, IComparable> propertyGetter)    {        var filter = new Filter<TFilterType, IComparable>(filterName, this.Items, this.FilteredItems, propertyGetter);        this.Filters.Add(filter);        foreach (var filterOption in filter.Options)        {            filterOption.IsSelectedChanged += this.OptionDisabled;        }    }    private void OptionDisabled(object sender, EventArgs e)    {        this.FilteredItems.Clear();        this.FilteredItems.Add(this.Items);        foreach (var filter in this.Filters)        {            filter.Refresh();        }    }}The implemented FilterManager provides the option to add any filter. You can do this with calling YourFilterManagerInstance.AddFilter(Name of the Filter, item => item.ItemProperty);One FilterManager can be shown in WPF with this XAML (and the right Setting to a proper ViewModel)<ItemsControl Grid.Row=1 ItemsSource={Binding BindingToFilterManager.Filters}>    <ItemsControl.ItemsPanel>        <ItemsPanelTemplate>            <StackPanel />        </ItemsPanelTemplate>    </ItemsControl.ItemsPanel>    <ItemsControl.ItemTemplate>        <DataTemplate>            <StackPanel>                <Separator />                <Expander Width=300>                    <Expander.Header>                        <TextBlock Text={Binding Name, Converter={StaticResource ToUpperCaseConverter}}                                   FontSize=16 FontWeight=SemiBold />                    </Expander.Header>                    <ItemsControl ItemsSource={Binding Options}>                        <ItemsControl.ItemsPanel>                            <ItemsPanelTemplate>                                <StackPanel />                            </ItemsPanelTemplate>                        </ItemsControl.ItemsPanel>                        <ItemsControl.ItemTemplate>                            <DataTemplate>                                <CheckBox Content={Binding Option} IsChecked={Binding IsSelected}                                          Margin=0, 3, 3, 3 />                            </DataTemplate>                        </ItemsControl.ItemTemplate>                    </ItemsControl>                </Expander>            </StackPanel>        </DataTemplate>    </ItemsControl.ItemTemplate></ItemsControl>
Implementing a filter
c#;wpf