WPF如何过滤一个ListBox

17

我有一个绑定到字符串列表的ListBox。当我在TextBox中输入文本时,我想过滤该列表。我该怎么做?

public void ListLoad()
{
    ElementList = new List<string>(); // creation a list of strings
    ElementList.Add("1"); // add a item of string
    ElementList.Add("2"); // add a item of string

    DataContext = this; // set the data context
}

我正在使用XAML绑定它:

ItemsSource="{Binding ElementList}"
3个回答

37

CollectionViewSource类可以帮助这里。据我所知,它具有许多功能来过滤、排序和分组集合。

ICollectionView view = CollectionViewSource.GetDefaultView(ElementList);
view.Filter = (o) => {return o;}//here is the lambda with your conditions to filter
当您不需要任何过滤器时,只需将view.Filter设置为null即可。此外,请查看有关筛选数据使用CollectionViewSource的文章。

11

这是一个用于绑定过滤器的附加属性:

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;
        }
    }
}

在 XAML 中使用时,可以按如下方式:

<DataGrid local:Filter.By="{Binding Filter}"
          ItemsSource="{Binding Foos}">
    ...

以及视图模型:

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;
    }
}

2
如果您将Dictionary设置为listbox的itemsource,请使用以下代码进行排序,
    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");
    }

上述代码返回包含“a”的项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接