SearchableComboBox.xaml 前端页面代码如下:
<UserControl x:Class="Test.Complexs.SearchableComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="200">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 带搜索功能的下拉框容器 -->
<Grid x:Name="SearchableComboBox2" Width="250" Height="30">
<!-- 显示选中项的文本框 -->
<TextBox x:Name="mySelectedItemTextBox" IsReadOnly="True" Padding="5,0,30,0" Background="White" BorderBrush="Silver" BorderThickness="1"/>
<!-- 下拉按钮 -->
<ToggleButton x:Name="myDropDownButton" Width="30" Height="30" HorizontalAlignment="Right" Click="myDropDownButton_Click">
<Path Fill="Black" Data="M 0 0 L 4 4 L 8 0 Z" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</ToggleButton>
<!-- 下拉面板 -->
<Popup x:Name="myDropDownPopup" Placement="Bottom" PlacementTarget="{Binding ElementName=SearchableComboBox}" AllowsTransparency="True" StaysOpen="False" Width="{Binding ActualWidth, ElementName=SearchableComboBox}">
<Border BorderBrush="Silver" BorderThickness="1" Background="White">
<StackPanel>
<!-- 搜索框 -->
<TextBox x:Name="mySearchTextBox" Margin="5" Padding="3" BorderBrush="Silver" BorderThickness="1" TextChanged="mySearchTextBox_TextChanged" KeyDown="mySearchTextBox_KeyDown" />
<!-- 下拉列表 -->
<ListBox x:Name="myItemsListBox" Height="150" Margin="0,0,0,5" SelectionChanged="myItemsListBox_SelectionChanged" MouseDoubleClick="myItemsListBox_MouseDoubleClick"/>
</StackPanel>
</Border>
</Popup>
</Grid>
<TextBlock Grid.Row="1" Margin="0,20,0,0" Text="选中的内容将显示在上方输入框中" Foreground="Gray"/>
</Grid>
</UserControl>
SearchableComboBox.xaml.cs 后端代码如下:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Test.Complexs
{
/// <summary>
/// SearchableComboBox.xaml 的交互逻辑
/// </summary>
public partial class SearchableComboBox : UserControl
{
// 原始数据源(实体类集合)
private List<City> _allCities;
// 过滤后的数据源
private ObservableCollection<City> _filteredCities;
// 当前选中的实体
private City _selectedCity;
public SearchableComboBox()
{
InitializeComponent();
// 初始化实体类数据
InitializeData();
// 初始化过滤后的集合
_filteredCities = new ObservableCollection<City>(_allCities);
myItemsListBox.ItemsSource = _filteredCities;
}
/// <summary>
/// 初始化实体类假数据
/// </summary>
private void InitializeData()
{
_allCities = new List<City>
{
new City(1, "北京"),
new City(2, "上海"),
new City(3, "广州"),
new City(4, "深圳"),
new City(5, "杭州"),
new City(6, "南京"),
new City(7, "成都"),
new City(8, "重庆"),
new City(9, "武汉"),
new City(10, "西安"),
new City(11, "苏州"),
new City(12, "郑州"),
new City(13, "青岛"),
new City(14, "长沙"),
new City(15, "天津")
};
}
/// <summary>
/// 下拉按钮点击事件
/// </summary>
private void myDropDownButton_Click(object sender, RoutedEventArgs e)
{
// 切换下拉面板显示状态
myDropDownPopup.IsOpen = !myDropDownPopup.IsOpen;
// 如果打开下拉面板,聚焦到搜索框
if (myDropDownPopup.IsOpen)
{
mySearchTextBox.Focus();
mySearchTextBox.Text = string.Empty;
}
}
/// <summary>
/// 搜索框文本变化事件 - 实时过滤
/// </summary>
private void mySearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
FilterItems(mySearchTextBox.Text);
}
/// <summary>
/// 根据搜索文本过滤实体类项目
/// </summary>
private void FilterItems(string searchText)
{
if (string.IsNullOrWhiteSpace(searchText))
{
// 搜索文本为空时显示所有项目
UpdateFilteredItems(_allCities);
}
else
{
// 过滤名称包含搜索文本的实体(不区分大小写)
var filtered = _allCities.Where(city =>
city.Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
UpdateFilteredItems(filtered);
}
}
/// <summary>
/// 更新过滤后的列表
/// </summary>
private void UpdateFilteredItems(List<City> items)
{
_filteredCities.Clear();
foreach (var item in items)
{
_filteredCities.Add(item);
}
}
/// <summary>
/// 列表项选择变化事件
/// </summary>
private void myItemsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (myItemsListBox.SelectedItem is City selectedCity)
{
// 保存选中的实体
_selectedCity = selectedCity;
// 回显选中项的名称
mySelectedItemTextBox.Text = selectedCity.Name;
// 可以在这里获取选中项的ID
// int selectedId = selectedCity.Id;
// 关闭下拉面板
myDropDownPopup.IsOpen = false;
// 清空选择,以便下次可以选择相同项
myItemsListBox.SelectedItem = null;
}
}
/// <summary>
/// 列表项双击事件
/// </summary>
private void myItemsListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (myItemsListBox.SelectedItem is City selectedCity)
{
_selectedCity = selectedCity;
mySelectedItemTextBox.Text = selectedCity.Name;
myDropDownPopup.IsOpen = false;
myItemsListBox.SelectedItem = null;
}
}
/// <summary>
/// 搜索框按键事件
/// </summary>
private void mySearchTextBox_KeyDown(object sender, KeyEventArgs e)
{
// 按Enter键选择第一个项目
if (e.Key == Key.Enter && _filteredCities.Count > 0)
{
_selectedCity = _filteredCities[0];
mySelectedItemTextBox.Text = _filteredCities[0].Name;
myDropDownPopup.IsOpen = false;
e.Handled = true;
}
// 按Esc键关闭下拉面板
else if (e.Key == Key.Escape)
{
myDropDownPopup.IsOpen = false;
e.Handled = true;
}
// 按向下箭头键聚焦到列表
else if (e.Key == Key.Down && _filteredCities.Count > 0)
{
myItemsListBox.Focus();
myItemsListBox.SelectedIndex = 0;
e.Handled = true;
}
}
}
/// <summary>
/// 城市实体类
/// </summary>
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public City(int id, string name)
{
Id = id;
Name = name;
}
// 重写ToString方法,用于在列表中显示
public override string ToString()
{
return Name;
}
}
}