如何在WinUI 3的DataGrid中创建可搜索/筛选的Combobox
WinUI 3 DataGrid 带搜索功能的下拉单元格实现方案
核心思路
放弃原生DataGridComboBoxColumn,改用DataGridTemplateColumn自定义单元格模板,嵌入带搜索能力的下拉控件(可基于AutoSuggestBox封装或直接使用),同时完成与DataGrid数据源的双向绑定。
实现步骤
1. 封装可搜索的下拉控件
先做一个复用性强的搜索下拉控件,利用AutoSuggestBox实现实时搜索过滤:
<UserControl x:Class="YourProjectNamespace.SearchableDropDown" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid> <AutoSuggestBox x:Name="SearchBox" PlaceholderText="输入关键词搜索..." TextChanged="SearchBox_TextChanged" SuggestionChosen="SearchBox_SuggestionChosen"/> </Grid> </UserControl>
后台代码处理搜索逻辑与绑定:
public sealed partial class SearchableDropDown : UserControl { // 下拉选项集合依赖属性 public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(IEnumerable), typeof(SearchableDropDown), new PropertyMetadata(null, OnItemsSourceChanged)); // 选中项依赖属性 public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(SearchableDropDown), new PropertyMetadata(null)); public IEnumerable ItemsSource { get => (IEnumerable)GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value); } public object SelectedItem { get => GetValue(SelectedItemProperty); set => SetValue(SelectedItemProperty, value); } public SearchableDropDown() { this.InitializeComponent(); } private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is SearchableDropDown control && e.NewValue is IEnumerable items) { control.SearchBox.ItemsSource = items; } } private void SearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) { // 仅在用户输入时触发过滤 if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput && ItemsSource != null) { var keyword = sender.Text.ToLower(); sender.ItemsSource = ItemsSource.Cast<object>() .Where(item => item.ToString().ToLower().Contains(keyword)) .ToList(); } } private void SearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) { SelectedItem = args.SelectedItem; sender.Text = args.SelectedItem.ToString(); } }
2. 在DataGrid中配置自定义列
将自定义搜索下拉控件嵌入DataGridTemplateColumn,区分显示模板和编辑模板:
<DataGrid x:Name="TargetDataGrid" ItemsSource="{Binding YourDataList}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTemplateColumn Header="带搜索的下拉列"> <!-- 非编辑状态显示文本 --> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding TargetProperty}" VerticalAlignment="Center" Margin="4"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!-- 编辑状态显示搜索下拉 --> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <local:SearchableDropDown ItemsSource="{Binding DataContext.DropDownOptions, ElementName=TargetDataGrid}" SelectedItem="{Binding TargetProperty, Mode=TwoWay}"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
3. 关键绑定说明
ItemsSource通过ElementName绑定到DataGrid上下文里的下拉选项集合,确保所有单元格共享同一数据源SelectedItem双向绑定到DataGrid每行数据的对应属性,实现选中值与数据源的同步- 非编辑状态用
TextBlock展示当前值,避免编辑控件一直显示影响性能
简易替代方案(无需自定义控件)
如果不需要复用控件,可直接在编辑模板里用AutoSuggestBox快速实现:
<DataGridTemplateColumn Header="带搜索的列"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding TargetProperty}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <AutoSuggestBox ItemsSource="{Binding DataContext.DropDownOptions, ElementName=TargetDataGrid}" Text="{Binding TargetProperty, Mode=TwoWay}" SuggestionChosen="AutoSuggestBox_SuggestionChosen"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn>
后台补充选中逻辑:
private void AutoSuggestBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) { var dataItem = sender.DataContext as YourDataModel; if (dataItem != null) { dataItem.TargetProperty = args.SelectedItem.ToString(); } }
内容的提问来源于stack exchange,提问作者Ammar Uddin
相关产品推荐
相关产品推荐

