How to make IcollectionView's Filter generic?

Emon Haque 3,176 Reputation points
2020-10-30T09:33:07.743+00:00

I've an ICollectionView wrapped in a Class<T>:

public class CollectionView<T> : ICollectionView
{
    ...
    ICollectionView view;
    public CollectionView(Collection<T> source)
    {
        ...
        view = CollectionViewSource.GetDefaultView(internalSource);
    }
    public Predicate<object> Filter { get => view.Filter; set => view.Filter = value; }
    ...
}

In my ViewModel, I define filter function like this:

Constructor()
{
    Items = new CollectionView<Item>(items);
    Items.Filter = filter;
}
...
bool filter(object o) => !((Item)o).IsInVisible;

so wherever I need filter, I've to cast the object o. How to make it generic in CollectionView<T> and avoid the extra step, casting?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,783 questions
0 comments No comments
{count} votes

Accepted answer
  1. gekka 9,586 Reputation points MVP
    2020-10-31T12:43:52.293+00:00
    namespace WpfApp1
    {
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.Collections.Specialized;
        using System.ComponentModel;
        using System.Globalization;
        using System.Windows;
        using System.Windows.Data;
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                System.Windows.Controls.ListBox listBox = new System.Windows.Controls.ListBox();
                listBox.SetBinding(System.Windows.Controls.ListBox.ItemsSourceProperty, new Binding());
                this.Content = listBox;
    
                List<Item> source = new List<Item>();
                source.Add(new Item() { IsInVisible = true });
                source.Add(new Item() { IsInVisible = false });
    
                var items = new CollectionView<Item>(source);
                items.Filter = filter;
    
                this.DataContext = items;
            }
    
            bool filter(Item item)
            {
                return item?.IsInVisible != true;
            }
    
            class Item
            {
                public bool IsInVisible { get; set; }
                public override string ToString() => IsInVisible.ToString();
            }
        }
    
        interface ICollectionView<T> : System.ComponentModel.ICollectionView
        {
            bool Contains(T item);
            bool MoveCurrentTo(T item);
            new Predicate<T> Filter { get; set; }
        }
    
        class CollectionView<T> : ICollectionView<T>
        {
            public CollectionView(System.ComponentModel.ICollectionView view)
            {
                if (_view == null) { throw new NullReferenceException(nameof(view)); }
    
                this._view = view;
            }
            public CollectionView(IEnumerable<T> source)
            {
                if (source is System.ComponentModel.ICollectionView v)
                {
                    _view = v;
                }
                else
                {
                    _view = CollectionViewSource.GetDefaultView(source);
                    if (_view == null) { throw new ArgumentException(nameof(source)); }
                }
            }
            private System.ComponentModel.ICollectionView _view;
    
            public Predicate<T> Filter
            {
                get => _Filter;
                set
                {
                    _Filter = value;
    
                    Predicate<object> fo = null;
                    if (value != null)
                    {
                        fo = new Predicate<object>((o) => value((T)o));
                    }
    
                    ((System.ComponentModel.ICollectionView)this).Filter = fo;
    
                }
            }
            private Predicate<T> _Filter;
    
            Predicate<object> System.ComponentModel.ICollectionView.Filter { get => _view.Filter; set => _view.Filter = value; }
    
            public bool Contains(T item) => _view.Contains(item);
            bool System.ComponentModel.ICollectionView.Contains(object item) => _view.Contains(item);
    
            public bool MoveCurrentTo(T item) => _view.Contains(item);
            bool System.ComponentModel.ICollectionView.MoveCurrentTo(object item) => _view.MoveCurrentTo(item);
            #region
            public void Refresh() => _view.Refresh();
            public IDisposable DeferRefresh() => _view.DeferRefresh();
            public bool MoveCurrentToFirst() => _view.MoveCurrentToFirst();
            public bool MoveCurrentToLast() => _view.MoveCurrentToLast();
            public bool MoveCurrentToNext() => _view.MoveCurrentToNext();
            public bool MoveCurrentToPosition(int position) => _view.MoveCurrentToPosition(position);
            public bool MoveCurrentToPrevious() => _view.MoveCurrentToPrevious();
            public CultureInfo Culture { get => _view.Culture; set => _view.Culture = value; }
            public IEnumerable SourceCollection => _view.SourceCollection;
            public bool CanFilter => _view.CanFilter;
            public SortDescriptionCollection SortDescriptions => _view.SortDescriptions;
            public bool CanSort => _view.CanSort;
            public bool CanGroup => _view.CanGroup;
            public ObservableCollection<GroupDescription> GroupDescriptions => _view.GroupDescriptions;
            public ReadOnlyObservableCollection<object> Groups => _view.Groups;
            public bool IsEmpty => _view.IsEmpty;
            public object CurrentItem => _view.CurrentItem;
            public int CurrentPosition => _view.CurrentPosition;
            public bool IsCurrentAfterLast => _view.IsCurrentAfterLast;
            public bool IsCurrentBeforeFirst => _view.IsCurrentBeforeFirst;
            public event CurrentChangingEventHandler CurrentChanging { add => _view.CurrentChanging += value; remove => _view.CurrentChanging -= value; }
            public event EventHandler CurrentChanged { add => _view.CurrentChanged += value; remove => _view.CurrentChanged -= value; }
            public IEnumerator GetEnumerator() => _view.GetEnumerator();
            public event NotifyCollectionChangedEventHandler CollectionChanged { add => _view.CollectionChanged += value; remove => _view.CollectionChanged -= value; }
            #endregion
        }  
    }
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.