WPF Filter a ListBox

后端 未结 3 1015
耶瑟儿~
耶瑟儿~ 2020-12-02 00:01

I have a ListBox with binding to a list of strings. I want to filter the list when I enter text in a TextBox. How can I do it?

publ         


        
相关标签:
3条回答
  • 2020-12-02 00:13

    If you set Dictionary as itemsource to listbox use the below code to sort,

        private void tb_filter_textChanged(object sender, TextChangedEventArgs e)
        {
            Dictionary<string, string> dictObject = new Dictionary<string, string>();
            ICollectionView view = CollectionViewSource.GetDefaultView(dictObject);
            view.Filter = CustomerFilter;
            listboxname.ItemsSource = view;
        }
    
        private bool CustomerFilter(object item)
        {
            KeyValuePair<string, string> Items = (KeyValuePair<string,string>) item;
            return Items.Value.ToString().Contains("a");
        }
    

    The above code returns the items contaning "a".

    0 讨论(0)
  • 2020-12-02 00:17

    Here is an attached property for binding a filter:

    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>), OnByChanged));
    
        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 OnByChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is ItemsControl itemsControl &&
                itemsControl.Items.CanFilter)
            {
                itemsControl.Items.Filter = (Predicate<object>)e.NewValue;
            }
        }
    }
    

    Used like this 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;
        }
    }
    
    0 讨论(0)
  • 2020-12-02 00:24

    CollectionViewSource class can help here. As far as I can tell it has many capabilities to filter, sort and group collections.

    ICollectionView view = CollectionViewSource.GetDefaultView(ElementList);
    view.Filter = (o) => {return o;}//here is the lambda with your conditions to filter
    

    When you don't need any filter just set view.Filter to null. Also check out this article on filtering

    0 讨论(0)
提交回复
热议问题