gpt4 book ai didi

c# - WPF 的自动完成组合框

转载 作者:太空狗 更新时间:2023-10-29 20:58:31 25 4
gpt4 key购买 nike

我需要一个用于 WPF C# 的自动完成组合框。我尝试了几种方法,但没有任何效果。例如,我尝试了一个组合框:

<ComboBox  Width="200"
IsEditable="True"
ItemsSource="{Binding Names}"
IsTextSearchEnabled="True"
HorizontalAlignment="Left"/>

Names 是一个字符串列表:Peter John、John、John Doe、Cathy、Howard、John Richards 等等

如果您输入名称,例如John 组合框应该展开,我应该看到

  • 约翰
  • 李四
  • 约翰·理查兹
  • 彼得·约翰

但这行不通。我该怎么做?

最佳答案

经过大量尝试,我终于找到了一个完整的、可行的解决方案。 (或者看起来是这样。)

第 1 步。修改 XAML 标记

您需要像这样修改 ComboBox:

<ComboBox
...
IsTextSearchEnabled="False"
...
PreviewTextInput="PreviewTextInput_EnhanceComboSearch"
PreviewKeyUp="PreviewKeyUp_EnhanceComboSearch"
DataObject.Pasting="Pasting_EnhanceComboSearch" />

即。 禁用默认文本搜索,并添加事件处理程序来处理用户添加、删除和粘贴文本。

第 2 步。添加将获取 ComboBox 的内部 TextBox 的辅助函数(因为 WPF)

为了使 PreviewTextInput_EnhanceComboSearchPasting_EnhanceComboSearch 正常工作,您需要访问 ComboBox 的插入符号。不幸的是,要做到这一点,您需要遍历,呃,视觉树(hat tip to Matt Hamilton)。您可以在扩展方法中执行此操作,但我在我的 Page 类中使用了静态方法:

public static T GetChildOfType<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) return null;

for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);

var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}

第 3 步。实现事件处理程序

请注意我用过

s => s.IndexOf(e.Text, StringComparison.InvariantCultureIgnoreCase) != -1 

这相当于不区分大小写的 s => s.Contains(e.Text) 检查。请记住更改该部分以满足您的需要。

步骤 3.a 用户在 ComboBox 中输入时触发搜索

运行PreviewTextInput 处理程序时,ComboBox 内的.Text 属性包含修改之前 的文本。因此,我们需要使用 GetChildOfType 方法获取 ComboBox 的内部 TextBox 以获取其插入符,以便我们知道键入的字符的确切插入位置。

private void PreviewTextInput_EnhanceComboSearch(object sender, TextCompositionEventArgs e)
{
ComboBox cmb = (ComboBox)sender;

cmb.IsDropDownOpen = true;

if (!string.IsNullOrEmpty(cmb.Text))
{
string fullText = cmb.Text.Insert(GetChildOfType<TextBox>(cmb).CaretIndex, e.Text);
cmb.ItemsSource = Names.Where(s => s.IndexOf(fullText, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else if (!string.IsNullOrEmpty(e.Text))
{
cmb.ItemsSource = Names.Where(s => s.IndexOf(e.Text, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else
{
cmb.ItemsSource = Names;
}
}

步骤 3.b 在用户粘贴到 ComboBox 时触发搜索

DataObject.Pasting 处理程序的行为方式与 PreviewTextInput 处理程序类似,因此我们再次需要插入符号。

private void Pasting_EnhanceComboSearch(object sender, DataObjectPastingEventArgs e)
{
ComboBox cmb = (ComboBox)sender;

cmb.IsDropDownOpen = true;

string pastedText = (string)e.DataObject.GetData(typeof(string));
string fullText = cmb.Text.Insert(GetChildOfType<TextBox>(cmb).CaretIndex, pastedText);

if (!string.IsNullOrEmpty(fullText))
{
cmb.ItemsSource = Names.Where(s => s.IndexOf(fullText, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else
{
cmb.ItemsSource = Names;
}
}

步骤 3.c 在用户删除 ComboBox 内的文本时触发搜索(并且还按空格键,因为 WPF)

这将在用户按下 Delete 或 Backspace 时触发。

还有 Space,因为 PreviewTextInput 忽略了 Space,所以在示例中很难从“John Doe”和“John Richards”中过滤掉“John”。

private void PreviewKeyUp_EnhanceComboSearch(object sender, KeyEventArgs e)
{
if (e.Key == Key.Back || e.Key == Key.Delete)
{
ComboBox cmb = (ComboBox)sender;

cmb.IsDropDownOpen = true;

if (!string.IsNullOrEmpty(cmb.Text))
{
cmb.ItemsSource = Names.Where(s => s.IndexOf(cmb.Text, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else
{
cmb.ItemsSource = Names;
}
}
}

...这应该足够了。

关于c# - WPF 的自动完成组合框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27963022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com