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

15

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

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

我可以通过使用两个控件而不是一个控件来拼凑出一个笨拙的解决方案,但我真的更希望有一个可以实现我想要的功能的控件。

更新:在进行了更多搜索后,我发现基本上相同的问题。那里提供的答案建议使用两个控件来“假装”它是所需的。

3个回答

20

我曾经遇到过同样的问题,寻找快速解决方案。

最终我还是自己写了一个解决方案。它有点不太规范,但如果需要,很容易将其变得更美观。

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

只需记得在重新构建组合框选项列表时将 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);”时会抛出异常。 - Ehsan
当数据源属性设置在组合框上时,我收到一个异常,指出无法删除该项。 - kuklei
@kuklei,使用数据绑定组合框无法完成此操作;像答案一样手动填充项目。 - Caius Jard

1

如何在C#中编写WinForms应用程序。 - ca9163d9

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接