Here is the attached property for filter binding:
using System; using System.Windows; using System.Windows.Controls; public static class Filter { public static readonly DependencyProperty ByProperty = DependencyProperty.RegisterAttached( "By", typeof(Predicate<object>), typeof(Filter), new PropertyMetadata(default(Predicate<object>), OnWithChanged)); public static void SetBy(ItemsControl element, Predicate<object> value) { element.SetValue(ByProperty, value); } public static Predicate<object> GetBy(ItemsControl element) { return (Predicate<object>)element.GetValue(ByProperty); } private static void OnWithChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UpdateFilter((ItemsControl)d, (Predicate<object>)e.NewValue); } private static void UpdateFilter(ItemsControl itemsControl, Predicate<object> filter) { if (itemsControl.Items.CanFilter) { itemsControl.Items.Filter = filter; } } }
Used as in xaml:
<DataGrid local:Filter.By="{Binding Filter}" ItemsSource="{Binding Foos}"> ...
And viewmodel:
public class ViewModel : INotifyPropertyChanged { private string filterText; private Predicate<object> filter; public event PropertyChangedEventHandler PropertyChanged; public ObservableCollection<Foo> Foos { get; } = new ObservableCollection<Foo>(); public string FilterText { get { return this.filterText; } set { if (value == this.filterText) return; this.filterText = value; this.OnPropertyChanged(); this.Filter = string.IsNullOrEmpty(this.filterText) ? (Predicate<object>)null : this.IsMatch; } } public Predicate<object> Filter { get { return this.filter; } private set { this.filter = value; this.OnPropertyChanged(); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool IsMatch(object item) { return IsMatch((Foo)item, this.filterText); } private static bool IsMatch(Foo item, string filterText) { if (string.IsNullOrEmpty(filterText)) { return true; } var name = item.Name; if (string.IsNullOrEmpty(name)) { return false; } if (filterText.Length == 1) { return name.StartsWith(filterText, StringComparison.OrdinalIgnoreCase); } return name.IndexOf(filterText, 0, StringComparison.OrdinalIgnoreCase) >= 0; } }
Johan larsson
source share