WPF,ComboBox,按类型显示候选人,但不自动完成?
WPF, ComboBox, Show candidates on type, but not auto-complete?
是否可以使 WPF ComboBox 像 Google 建议的工作方式一样显示下面的候选内容,但不自动完成输入字段中的其余文本?
例如,如果我在底部的 WPF 代码中键入“b”,我会得到这个。
但这会导致使用文本组合的亚洲语言 IME 出现一些问题。此外,这不会显示所有其他以“b”开头的候选人。相反,我可以让 WPF ComboBox 像这样显示,并让用户 select 使用方向键和制表符作为候选项,就像大多数 IDE 文本编辑器一样吗?
<ComboBox HorizontalAlignment="Left" Margin="111,61,0,0" VerticalAlignment="Top" Width="120" IsEditable="True">
<ComboBoxItem Content="Alice"/>
<ComboBoxItem Content="Bob"/>
<ComboBoxItem Content="Bart"/>
<ComboBoxItem Content="Bort"/>
<ComboBoxItem Content="Charlie"/>
</ComboBox>
可以根据输入的文本过滤 ItemsSource 集合的项目。
但是,在我看来,不可能更改第一个合适的自动选择 - 这种行为嵌套在 ComboBox 逻辑中。
并且无法区分用户输入和第一个元素的文本。
正因如此,过滤也无法正确配置。
如果不更改 ComboBox 模板或将其替换为您自己的自定义元素,我认为是无法实现的。
基于 Expander 的实施示例:
首先,永远不要用 UI 项填充组合框、列表框(和其他 ItemsControl)。
创建一个可观察集合并将其传递给 ItemsSource。
其次,获取此集合的表示并在其过滤器中设置 属性 用于过滤元素的处理程序方法。
它应该将传递给 ItemsSource 的集合的元素与指定过滤器模板的 Text 值进行比较。
如果 Text 为空 (string.IsNullOrWhiteSpace (Text) = true),则过滤器应跳过所有元素。
三、当Text发生变化时,在collection view上调用Refrech
<Window x:Class="FilterComboBox.FilterComboBoxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FilterComboBox"
mc:Ignorable="d"
Title="FilterComboBoxWindow" Height="450" Width="800">
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Expander>
<Expander.Header>
<TextBox x:Name="tBox" MinWidth="100"
TextChanged="OnTextChanged"/>
</Expander.Header>
<ListBox x:Name="listBox" SelectionChanged="OnSelectionChanged"/>
<Expander.Style>
<Style TargetType="Expander">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsExpanded" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</Expander.Style>
</Expander>
<TextBlock Grid.Row="1" Text="{Binding SelectedItem, ElementName=listBox}"/>
</Grid>
</Window>
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace FilterComboBox
{
/// <summary>
/// Логика взаимодействия для FilterComboBoxWindow.xaml
/// </summary>
public partial class FilterComboBoxWindow : Window
{
private readonly ObservableCollection<string> contetnItems
= new ObservableCollection<string>()
{
"Alice",
"Bob",
"Bart",
"Bort",
"Charlie"
};
public FilterComboBoxWindow()
{
InitializeComponent();
ICollectionView view = CollectionViewSource.GetDefaultView(contetnItems);
view.Filter = OnFilter;
listBox.ItemsSource = contetnItems;
}
private bool OnFilter(object obj)
{
return
string.IsNullOrWhiteSpace(tBox.Text) ||
((obj is string text) && text.ToUpper().StartsWith(tBox.Text.ToUpper()));
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
tBox.Text = listBox.SelectedItem?.ToString();
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(contetnItems).Refresh();
}
}
}
P.S.其中大部分使用 MVVM 模式更方便、更正确。
是否可以使 WPF ComboBox 像 Google 建议的工作方式一样显示下面的候选内容,但不自动完成输入字段中的其余文本?
例如,如果我在底部的 WPF 代码中键入“b”,我会得到这个。
但这会导致使用文本组合的亚洲语言 IME 出现一些问题。此外,这不会显示所有其他以“b”开头的候选人。相反,我可以让 WPF ComboBox 像这样显示,并让用户 select 使用方向键和制表符作为候选项,就像大多数 IDE 文本编辑器一样吗?
<ComboBox HorizontalAlignment="Left" Margin="111,61,0,0" VerticalAlignment="Top" Width="120" IsEditable="True">
<ComboBoxItem Content="Alice"/>
<ComboBoxItem Content="Bob"/>
<ComboBoxItem Content="Bart"/>
<ComboBoxItem Content="Bort"/>
<ComboBoxItem Content="Charlie"/>
</ComboBox>
可以根据输入的文本过滤 ItemsSource 集合的项目。
但是,在我看来,不可能更改第一个合适的自动选择 - 这种行为嵌套在 ComboBox 逻辑中。
并且无法区分用户输入和第一个元素的文本。
正因如此,过滤也无法正确配置。
如果不更改 ComboBox 模板或将其替换为您自己的自定义元素,我认为是无法实现的。
基于 Expander 的实施示例:
首先,永远不要用 UI 项填充组合框、列表框(和其他 ItemsControl)。
创建一个可观察集合并将其传递给 ItemsSource。
其次,获取此集合的表示并在其过滤器中设置 属性 用于过滤元素的处理程序方法。
它应该将传递给 ItemsSource 的集合的元素与指定过滤器模板的 Text 值进行比较。
如果 Text 为空 (string.IsNullOrWhiteSpace (Text) = true),则过滤器应跳过所有元素。
三、当Text发生变化时,在collection view上调用Refrech
<Window x:Class="FilterComboBox.FilterComboBoxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FilterComboBox"
mc:Ignorable="d"
Title="FilterComboBoxWindow" Height="450" Width="800">
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Expander>
<Expander.Header>
<TextBox x:Name="tBox" MinWidth="100"
TextChanged="OnTextChanged"/>
</Expander.Header>
<ListBox x:Name="listBox" SelectionChanged="OnSelectionChanged"/>
<Expander.Style>
<Style TargetType="Expander">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsExpanded" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</Expander.Style>
</Expander>
<TextBlock Grid.Row="1" Text="{Binding SelectedItem, ElementName=listBox}"/>
</Grid>
</Window>
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace FilterComboBox
{
/// <summary>
/// Логика взаимодействия для FilterComboBoxWindow.xaml
/// </summary>
public partial class FilterComboBoxWindow : Window
{
private readonly ObservableCollection<string> contetnItems
= new ObservableCollection<string>()
{
"Alice",
"Bob",
"Bart",
"Bort",
"Charlie"
};
public FilterComboBoxWindow()
{
InitializeComponent();
ICollectionView view = CollectionViewSource.GetDefaultView(contetnItems);
view.Filter = OnFilter;
listBox.ItemsSource = contetnItems;
}
private bool OnFilter(object obj)
{
return
string.IsNullOrWhiteSpace(tBox.Text) ||
((obj is string text) && text.ToUpper().StartsWith(tBox.Text.ToUpper()));
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
tBox.Text = listBox.SelectedItem?.ToString();
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(contetnItems).Refresh();
}
}
}
P.S.其中大部分使用 MVVM 模式更方便、更正确。