在WPF中,实现ComboBox多选,并且可以根据输入值动态显示下拉框
时间: 2024-03-21 22:39:04 浏览: 261
在WPF中,实现ComboBox多选可以通过设置ComboBox的IsEditable属性为True,并使用一个TextBlock来显示选中项,同时在ComboBox的Popup部分添加一个ItemsControl用于显示下拉选项。当用户输入时,我们可以动态地过滤下拉选项。以下是一个简单的实现示例:
```xml
<ComboBox IsEditable="True"
Text="{Binding SelectedText}"
PreviewTextInput="ComboBox_PreviewTextInput"
PreviewKeyDown="ComboBox_PreviewKeyDown">
<ComboBox.Template>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton x:Name="ToggleButton"
Content="{TemplateBinding SelectionBoxItem}"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"/>
<ContentPresenter x:Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
Margin="3,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
<Popup x:Name="Popup"
IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"
StaysOpen="False">
<Grid>
<Border x:Name="DropDownBorder"
Background="White"
BorderThickness="1"
BorderBrush="LightGray">
<ScrollViewer>
<ItemsControl x:Name="ItemsControl"
ItemsSource="{TemplateBinding ItemsSource}"
ItemTemplate="{TemplateBinding ItemTemplate}"
SelectionMode="Multiple"/>
</ScrollViewer>
</Border>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Visibility" Value="Collapsed" TargetName="DropDownBorder"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
<DataTrigger Binding="{Binding Path=Text.Length, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="SelectedIndex" Value="-1" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ComboBox.Template>
</ComboBox>
```
在ViewModel中需要为ComboBox绑定一个ItemsSource和一个SelectedText属性,以及处理PreviewTextInput和PreviewKeyDown事件。在事件处理程序中,我们可以动态地过滤下拉选项并更新选中项。
```csharp
private ObservableCollection<string> _options = new ObservableCollection<string>();
public ObservableCollection<string> Options
{
get { return _options; }
set { _options = value; OnPropertyChanged(nameof(Options)); }
}
private string _selectedText;
public string SelectedText
{
get { return _selectedText; }
set { _selectedText = value; OnPropertyChanged(nameof(SelectedText)); }
}
private void ComboBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
var comboBox = sender as ComboBox;
var text = comboBox.Text + e.Text;
comboBox.ItemsSource = Options.Where(o => o.ToLower().Contains(text.ToLower()));
}
private void ComboBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var comboBox = sender as ComboBox;
var selectedItems = comboBox.GetSelectedItems<string>();
if (selectedItems.Any())
{
SelectedText = string.Join(",", selectedItems);
}
else
{
SelectedText = comboBox.Text;
}
comboBox.IsDropDownOpen = false;
}
}
```
注意,在事件处理程序中,我们使用了一个扩展方法GetSelectedItems,它可以获取选中项的值列表。
```csharp
public static class ComboBoxExtensions
{
public static IEnumerable<T> GetSelectedItems<T>(this ComboBox comboBox)
{
var items = comboBox.ItemsSource as IEnumerable<T>;
if (items == null) yield break;
foreach (var item in items)
{
var container = comboBox.ItemContainerGenerator.ContainerFromItem(item) as ComboBoxItem;
if (container != null && container.IsSelected)
{
yield return item;
}
}
}
}
```
阅读全文