📜  键入时的 wpf 组合框过滤器 (1)

📅  最后修改于: 2023-12-03 14:58:16.716000             🧑  作者: Mango

WPF组合框过滤器示例

在WPF应用程序中,组合框(ComboBox)是常用的用户界面(UI)元素之一。它可以让用户从预定义选项列表中选择一个值。但是,对于较大的列表,用户可能需要过滤选项以快速找到所需的项。本示例演示如何在组合框中实现一个简单的过滤器,以便根据用户输入动态筛选选项。

前提条件

要使用本示例,您需要具备以下要求:

  • Visual Studio 2019或更高版本
  • .NET Framework 4.7.2或更高版本
  • 基本的WPF和C#编程知识
步骤
  1. 创建新的WPF应用程序项目。
  2. 在MainWindow.xaml中添加以下XAML代码,它包含一个ComboBox元素和一个TextBox元素。ComboBox的ItemsSource绑定到string类型的列表(例如List<string>),并且其SelectedItem和Text属性分别绑定到ViewModel中的SelectedOption和FilterText属性。
<Window x:Class="ComboBoxFiltering.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Margin="10" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}" />
        <ComboBox Grid.Row="1" Margin="10" 
                  ItemsSource="{Binding Options}" 
                  SelectedItem="{Binding SelectedOption}"
                  Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}" 
                  IsEditable="True"
                  IsTextSearchEnabled="False" />
    </Grid>
</Window>
  1. 创建一个名为MainViewModel的类。该类应包含一个名为"Options"的公共属性,它是一个字符串列表,表示ComboBox中的选项。它还应该包含名为"SelectedOption"的属性,表示所选选项。最后还需要一个名为"FilterText"的属性,表示用户正在输入的文本,以用于过滤选项。
using System.Collections.ObjectModel;
using System.Linq;

namespace ComboBoxFiltering
{
    public class MainViewModel : NotifyPropertyChanged
    {
        private string _selectedOption;
        public string SelectedOption
        {
            get => _selectedOption;
            set
            {
                _selectedOption = value;
                OnPropertyChanged();
            }
        }

        private ObservableCollection<string> _options;
        public ObservableCollection<string> Options
        {
            get => _options;
            set
            {
                _options = value;
                OnPropertyChanged();
            }
        }

        private string _filterText;
        public string FilterText
        {
            get => _filterText;
            set
            {
                _filterText = value;
                ApplyFilter();
            }
        }

        private void ApplyFilter()
        {
            var filteredOptions = _options.Where(o => o.StartsWith(_filterText ?? "", System.StringComparison.OrdinalIgnoreCase)).ToList();
            if (filteredOptions.Count == 1)
            {
                SelectedOption = filteredOptions.First();
            }
            else
            {
                SelectedOption = null;
            }
            Options = new ObservableCollection<string>(filteredOptions);
        }

        public MainViewModel()
        {
            Options = new ObservableCollection<string>
            {
                "Abby",
                "Barry",
                "Chloe",
                "Dan",
                "Emma",
                "Frank",
                "George",
                "Hannah",
                "Isabelle",
                "Jack",
                "Katie",
                "Liam",
                "Mia",
                "Nathan",
                "Olivia",
                "Peter",
                "Quinn",
                "Rachel",
                "Sam",
                "Tom",
                "Violet",
                "Wendy",
                "Xander",
                "Yara",
                "Zoe"
            };
        }
    }
}
  1. 创建另一个类,名为NotifyPropertyChanged。它应该实现 INotifyPropertyChanged 接口并包含一个名为 OnPropertyChanged 的方法。之所以需要此类,是因为ViewModel中的属性必须有通知机制,以便UI可以在值更改时更新。
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace ComboBoxFiltering
{
    public class NotifyPropertyChanged : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
  1. 将MainViewModel实例化并将其设置为窗口的DataContext。确保在MainWindow构造函数中创建视图模型,并在ViewModel中设置SelectedOption属性的默认值。此示例中,我已经手动将"Abby"设置为默认选项。
using System.Windows;

namespace ComboBoxFiltering
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel
            {
                SelectedOption = "Abby"
            };
        }
    }
}
说明

在此示例中,我们使用了以下方法:

  • 绑定SelectedItem和Text属性。这两个属性互相关联,以便在用户选择选项或键入文本时更新。
  • 在TextBox中,我们使用UpdateSourceTrigger = PropertyChanged属性,以便每次用户更改文本时,ViewModel的FilterText属性都会被更新。
  • 在ComboBox中,我们将IsEditable属性设置为True,以便用户可以键入文本。我们还将IsTextSearchEnabled属性设置为False,因为我们正在自己实现过滤器,而不是信赖ComboBox的内置搜索功能。
  • 在ViewModel中,我们使用ObservableCollection,以便在添加或删除选项时,UI始终能够保持同步。
  • 当用户输入文本时,我们使用Linq的Where方法动态筛选选项列表,并将新列表分配给Options属性。我们还尝试自动选择列表中的项。如果过滤后的列表中只有一项,我们将其设置为SelectedOption属性的值。
  • 我们使用INotifyPropertyChanged接口和NotifyPropertyChanged基类来实现视图模型中的通知机制。这使得UI可以在属性更改时得到通知,从而更新。
结论

这个简单的示例演示了如何实现一个方便的过滤器来过滤组合框中的选项。您可以根据需要进行扩展,添加搜索排序或其他功能。

Markdown代码
# WPF组合框过滤器示例

在WPF应用程序中,组合框(ComboBox)是常用的用户界面(UI)元素之一。它可以让用户从预定义选项列表中选择一个值。但是,对于较大的列表,用户可能需要过滤选项以快速找到所需的项。本示例演示如何在组合框中实现一个简单的过滤器,以便根据用户输入动态筛选选项。

## 前提条件

要使用本示例,您需要具备以下要求:

* Visual Studio 2019或更高版本
* .NET Framework 4.7.2或更高版本
* 基本的WPF和C#编程知识

## 步骤

1. 创建新的WPF应用程序项目。
2. 在MainWindow.xaml中添加以下XAML代码,它包含一个ComboBox元素和一个TextBox元素。ComboBox的ItemsSource绑定到string类型的列表(例如List<string>),并且其SelectedItem和Text属性分别绑定到ViewModel中的SelectedOption和FilterText属性。
3. 创建一个名为MainViewModel的类。该类应包含一个名为"Options"的公共属性,它是一个字符串列表,表示ComboBox中的选项。它还应该包含名为"SelectedOption"的属性,表示所选选项。最后还需要一个名为"FilterText"的属性,表示用户正在输入的文本,以用于过滤选项。
4. 创建另一个类,名为NotifyPropertyChanged。它应该实现 INotifyPropertyChanged 接口并包含一个名为 OnPropertyChanged 的方法。之所以需要此类,是因为ViewModel中的属性必须有通知机制,以便UI可以在值更改时更新。
5. 将MainViewModel实例化并将其设置为窗口的DataContext。确保在MainWindow构造函数中创建视图模型,并在ViewModel中设置SelectedOption属性的默认值。此示例中,我已经手动将"Abby"设置为默认选项。

## 说明

在此示例中,我们使用了以下方法:

* 绑定SelectedItem和Text属性。这两个属性互相关联,以便在用户选择选项或键入文本时更新。
* 在TextBox中,我们使用UpdateSourceTrigger = PropertyChanged属性,以便每次用户更改文本时,ViewModel的FilterText属性都会被更新。
* 在ComboBox中,我们将IsEditable属性设置为True,以便用户可以键入文本。我们还将IsTextSearchEnabled属性设置为False,因为我们正在自己实现过滤器,而不是信赖ComboBox的内置搜索功能。
* 在ViewModel中,我们使用ObservableCollection<string>,以便在添加或删除选项时,UI始终能够保持同步。
* 当用户输入文本时,我们使用Linq的Where方法动态筛选选项列表,并将新列表分配给Options属性。我们还尝试自动选择列表中的项。如果过滤后的列表中只有一项,我们将其设置为SelectedOption属性的值。
* 我们使用INotifyPropertyChanged接口和NotifyPropertyChanged基类来实现视图模型中的通知机制。这使得UI可以在属性更改时得到通知,从而更新。

## 结论

这个简单的示例演示了如何实现一个方便的过滤器来过滤组合框中的选项。您可以根据需要进行扩展,添加搜索排序或其他功能。