问题描述
我需要WPF C#的自动完成组合框。我尝试了几种方法,但没有任何效果。例如,我尝试了一个组合框:
I need an autocomplete combobox for WPF C#. I've tried several approaches but nothing works. For example I've tried a combobox:
<ComboBox Width="200"
IsEditable="True"
ItemsSource="{Binding Names}"
IsTextSearchEnabled="True"
HorizontalAlignment="Left"/>
名称
是字符串列表:Peter约翰,约翰,约翰·杜伊,凯茜,霍华德,约翰·理查兹等
Names
is a List of Strings: Peter John, John, John Doe, Cathy, Howard, John Richards and so on
如果您输入名称,例如John组合框应该扩大,我应该看到
If you type in a name e.g. John the combobox should expand and I should see
- John
- John Doe
- John Richards
- Peter John
- John
- John Doe
- John Richards
- Peter John
但这不起作用。我该怎么办?
But that doesn't work. How can I do that?
推荐答案
经过多番摆弄,我设法找到了一个完整的,可行的解决方案。 (或者看起来是这样。)
After a lot of fiddling, I have managed to arrive at a complete, working solution. (Or so it seems.)
您需要像修改ComboBox一样因此:
You need to modify your ComboBox like so:
<ComboBox
...
IsTextSearchEnabled="False"
...
PreviewTextInput="PreviewTextInput_EnhanceComboSearch"
PreviewKeyUp="PreviewKeyUp_EnhanceComboSearch"
DataObject.Pasting="Pasting_EnhanceComboSearch" />
ie。来禁用 默认文本搜索,并添加事件处理程序,该处理程序将负责用户添加,删除和粘贴文本。
ie. to disable default text search, and add events handlers that will take care of user adding, deleting and pasting text.
为了 PreviewTextInput_EnhanceComboSearch
和 Pasting_EnhanceComboSearch
都可以使用,则需要访问ComboBox的插入符号。不幸的是,要做到这一点,您需要遍历所有视觉树()。您可以使用扩展方法来做到这一点,但是我在 Page
类中使用了静态方法:
In order for PreviewTextInput_EnhanceComboSearch
and Pasting_EnhanceComboSearch
to work at all, you will need to access your ComboBox's caret. Unfortunately, to do this, you need to traverse, er, visual tree (hat tip to Matt Hamilton). You can do that in an extension method, but I used a static one in my Page
class:
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。实施事件处理程序
请注意我用过
Step 3. Implement event handlers
Please note I used
s => s.IndexOf(e.Text, StringComparison.InvariantCultureIgnoreCase) != -1
-不敏感 s => s.Contains(e.Text)
检查。
当运行 PreviewTextInput
处理程序时,组合框内的 .Text
属性包含之前的文本已被修改。因此,我们需要使用 GetChildOfType
方法获取ComboBox的内部TextBox以获得其插入符,以便我们确切知道在何处插入了键入字符。
When a PreviewTextInput
handler is run, the .Text
property inside the ComboBox contains the text from before it was modified. Therefore, we need to get ComboBox's internal TextBox using GetChildOfType
method in order to obtain its caret, so we know where exactly was the typed character inserted.
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
hanlder,所以我们再次需要插入符号。
Step 3.b Trigger search on user pasting into ComboBox
DataObject.Pasting
handler behaves in a similar fashion to PreviewTextInput
hanlder, so we need the caret again.
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键时触发。
Step 3.c Trigger search on user deleting text inside ComboBox (and also pressing Space, because WPF)
This will trigger when the user depresses either Delete or Backspace.
还有空格,因为 PreviewTextInput
忽略了空格,所以在示例中很难从 John Doe和 John Richards中滤除 John
And also Space, because Space is ignored by PreviewTextInput
, so it would be difficult to filter out "John" from "John Doe" and "John Richards" in the example.
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;
}
}
}
...这应该足够了。
...and that should probably be enough.
这篇关于WPF的自动完成组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!