覆盖 Winforms ComboBox 自动完成建议规则

Posted

技术标签:

【中文标题】覆盖 Winforms ComboBox 自动完成建议规则【英文标题】:Override Winforms ComboBox Autocomplete Suggest Rule 【发布时间】:2011-01-16 13:47:30 【问题描述】:

我正在尝试修改 Windows.Forms ComboBox 的行为,以便自动完成下拉菜单根据我指定的规则显示项目。

默认情况下,如果您在 ComboBox 中使用 AutoComplete,则遵循的规则是“字符串 s 包含在下拉列表中 if(s.StartsWith(userEnteredTextInTheComboBox))”我真正感兴趣的只是替换一个新规则对于当前的,但我无法找到它。 (具体来说,我更喜欢 s.Contains 而不是 s.StartsWith。)

我可以使用两个控件而不是一个控件来拼凑一个笨拙的解决方案,但我真的会更高兴有一个能真正做到我想要的。

更新:经过更多搜索,我基本上找到了the same question。那里提供的答案表明使用两个控件来“伪造”是要走的路。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,正在寻找快速解决方案。

最后我自己写了。它有点脏,但如果需要的话,让它变得更漂亮应该不难。

这个想法是在每次按键后重新构建组合列表。这样我们就可以依赖combo的内置接口了,我们不需要用文本框和列表框来实现我们自己的接口...

如果您重新构建组合的选项列表,请记住将 combo.Tag 设置为 null

private void combo_KeyPress(object sender, KeyPressEventArgs e) 
    comboKeyPressed();


private void combo_TextChanged(object sender, EventArgs e) 
    if (combo.Text.Length == 0) comboKeyPressed();


private void comboKeyPressed() 
    combo.DroppedDown = true;

    object[] originalList = (object[])combo.Tag;
    if (originalList == null) 
        // backup original list
        originalList = new object[combo.Items.Count];
        combo.Items.CopyTo(originalList, 0);
        combo.Tag = originalList;
    

    // prepare list of matching items
    string s = combo.Text.ToLower();
    IEnumerable<object> newList = originalList;
    if (s.Length > 0) 
        newList = originalList.Where(item => item.ToString().ToLower().Contains(s));
    

    // clear list (loop through it, otherwise the cursor would move to the beginning of the textbox...)
    while (combo.Items.Count > 0) 
        combo.Items.RemoveAt(0);
    

    // re-set list
    combo.Items.AddRange(newList.ToArray());

【讨论】:

我做到了,但我应该移动这一行“combo.DroppedDown = true;”为了成为函数的最后一行。否则在尝试删除最后一项“combo.Items.RemoveAt(0);”时会引发异常 我收到一个异常,抱怨在组合上设置数据源属性时无法删除项目 @kuklei 这不能通过数据绑定组合完成;像答案一样手动填充项目【参考方案2】:

在 Windows Vista 之前,自动完成对象match candidates with prefix only,所以你需要cook your own。

如果您需要在建议列表可见时重置它,use IAutoCompleteDropDown::ResetEnumerator。

【讨论】:

如何在 c# 中为 winforms 编写【参考方案3】:

感谢 Ehsan。 仅供参考。我最终得到了这个。

    private void comboBoxIdentification_TextChanged(object sender, EventArgs e)
    
        if (comboBoxIdentification.Text.Length == 0)
        
            comboBoxIdentificationKeyPressed(comboBoxIdentification, comboBoxIdentification.Text);
        
    

    private void comboBoxIdentificationKeyPressed(ComboBox comboBoxParm, string text )
    
        comboBoxParm.DroppedDown = true;
        object[] originalList = (object[])comboBoxParm.Tag;
        if (originalList == null)
        
            // backup original list
            originalList = new object[comboBoxParm.Items.Count];
            comboBoxParm.Items.CopyTo(originalList, 0);
            comboBoxParm.Tag = originalList;
        

        // prepare list of matching items
        string s = text.ToLower();
        IEnumerable<object> newList = originalList;
        if (s.Length > 0)
        
            newList = originalList.Where(item => item.ToString().ToLower().Contains(s));
        

        // clear list (loop through it, otherwise the cursor would move to the beginning of the textbox...)
        while (comboBoxParm.Items.Count > 0)
        
            comboBoxParm.Items.RemoveAt(0);
        
        var newListArr = newList.ToArray();
        // re-set list
        comboBoxParm.Items.AddRange(newListArr);
    

【讨论】:

以上是关于覆盖 Winforms ComboBox 自动完成建议规则的主要内容,如果未能解决你的问题,请参考以下文章

子字符串上的组合框自动完成

C# - Winforms - Combobox - 避免选择更新数据源的第一项

为什么在datagridview中对combobox使用自动完成时有两个列表?

当 DataSource 值更改时,WinForms ComboBox 中的项目不会更新

WinForms ComboBox DropDown 和 Autocomplete 窗口都出现

检测何时在 Winforms 上单击 ComboBox