Just for reference, another way is to use an attached property on the CollectionViewSource
which then pipes the functions to the ViewModel
(Implementing an Interface).
This is a very basic Demonstration just for filtering, it would need some work for e.g. a second Collection on the VM but i think it's enough to show the general technique.
If this is better or worse than the other methods is up for discussion, i just wanted to point out, that there's another way of doing this
Definition of attached Property:
public static class CollectionViewSourceFilter
{
public static IFilterCollectionViewSource GetFilterObject(CollectionViewSource obj)
{
return (IFilterCollectionViewSource)obj.GetValue(FilterObjectProperty);
}
public static void SetFilterObject(CollectionViewSource obj, IFilterCollectionViewSource value)
{
obj.SetValue(FilterObjectProperty, value);
}
public static void FilterObjectChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue is IFilterCollectionViewSource oldFilterObject
&& sender is CollectionViewSource oldCvs)
{
oldCvs.Filter -= oldFilterObject.Filter;
oldFilterObject.FilterRefresh -= (s, e2) => oldCvs.View.Refresh();
}
if (e.NewValue is IFilterCollectionViewSource filterObject
&& sender is CollectionViewSource cvs)
{
cvs.Filter += filterObject.Filter;
filterObject.FilterRefresh += (s,e2) => cvs.View.Refresh();
}
}
public static readonly DependencyProperty FilterObjectProperty = DependencyProperty.RegisterAttached(
"FilterObject",
typeof(Interfaces.IFilterCollectionViewSource),
typeof(CollectionViewSourceFilter),
new PropertyMetadata(null,FilterObjectChanged)
);
}
Interface:
public interface IFilterCollectionViewSource
{
void Filter(object sender, FilterEventArgs e);
event EventHandler FilterRefresh;
}
usage in xaml:
<CollectionViewSource
x:Key="yourKey"
Source="{Binding YourCollection}"
classes:CollectionViewSourceFilter.FilterObject="{Binding}" />
and usage in the ViewModel:
class YourViewModel : IFilterCollectionViewSource
{
public event EventHandler FilterRefresh;
private string _SearchTerm = string.Empty;
public string SearchTerm
{
get { return _SearchTerm; }
set {
SetProperty(ref _SearchTerm, value);
FilterRefresh?.Invoke(this, null);
}
}
private ObservableCollection<YourItemType> _YourCollection = new ObservableCollection<YourItemType>();
public ObservableCollection<YourItemType> YourCollection
{
get { return _YourCollection; }
set { SetProperty(ref _YourCollection, value); }
}
public void Filter(object sender, FilterEventArgs e)
{
e.Accepted = (e.Item as YourItemType)?.YourProperty?.ToLower().Contains(SearchTerm.ToLower()) ?? true;
}
}
scm:
is thisxmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
– Blowtorch