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

时间:2010-02-13 21:09:35

标签: c# winforms combobox autocomplete

我正在尝试修改Windows.Forms ComboBox的行为,以便AutoComplete下拉列表根据我指定的规则显示项目。

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

我可以使用两个控件而不是一个控制器将一个笨拙的解决方案整合在一起,但我真的很高兴实际上做了我想做的事情。

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

3 个答案:

答案 0 :(得分:18)

我遇到了同样的问题,并寻求快速解决方案。

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

我们的想法是在每次按键后重新构建组合列表。这样我们可以依赖于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());
}

答案 1 :(得分:2)

在Windows Vista之前,自动填充对象match candidates with prefix only,因此您需要cook your own

如果您需要重置建议清单use IAutoCompleteDropDown::ResetEnumerator

答案 2 :(得分:0)

感谢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);
    }