How can I prevent auto-select in ComboBox on drop-down except for exact matches?

家住魔仙堡 提交于 2019-12-23 12:25:58

问题


I have a ComboBox that is part of a detail display related to a data grid containing rows from a database. No binding to the ComboBox exists, I am doing this manually. The ComboBox allows manual entry, as if it were a text field, while still providing a drop-down of choices.

My issue is that if I have manually entered text in the field, and the drop-down is clicked, the ComboBox apparently wants to seek out a match. Also, it appears that the search is simple, so KG matches KG/Day. I must avoid this and force an exact match.

But further, I think I need to be able to govern the entire process myself, because to further complicate the matter, the drop-down item would actually read KG/Day - kilograms/day. The database field from which the data is fetched, however, is only storing the portion prior to the hyphen, so KG/Day.

So, I need to intercept the drop-down action in a way that allows me to do two things:

1) Perform my own search to find whether or not I have ad-hoc text, or a "real" match. As in that it was originally selected from the drop-down; in other words, that I have KG/Day and not just KG.

2) Eliminate the auto-search behavior that ComboBox wants to do.

I have tried getting in front of these things using method handlers in the Form, such as

ComboBox::DropDown() and ComboBox::DropDownClosed(),

but it seems these still don't allow me to stop the basic ComboBox searching/matching.

I have also tried creating a class of my own inherited from ComboBox, but I don't really know what to override, or in general how to go about getting what I want, stopping what I don't.

So, with that, I thank you for your advice.

EDIT: to expand on what I tried already... In my inherited class, I was attempting to use a WndProc override. Based on some advice I found in another forum, my goal was to intercept the ComboBox message LB_FINDSTRING and replace it with LB_FINDSTRINGEXACT. The post suggested that ComboBox defaulted to LB_FiNDSTRING, which fits what I see it doing, and that subbing LB_FINDSTRINGEXACT would cure the problem. Trouble is, unless I got a bad definition for LB_FINDSTRING, it was never received.

Here's my enum:

[Flags]
public enum ListBoxFlags
{
    LB_ADDSTRING = 0x0180,
    LB_SETSEL = 0x0185,
    LB_GETSELITEMS = 0x0191,
    LB_GETSELCOUNT = 0x0190,
    LB_GETCURSEL = 0x0188,
    LB_SELECTSTRING = 0x018C,
    LB_SETCURSEL = 0x0186,
    LB_FINDSTRING = 0x018F,
    LB_FINDSTRINGEXACT = 0x01A2,
    LB_GETCOUNT = 0x018B,
    LB_GETSEL = 0x0187,
    LB_GETTEXT = 0x0189,
    LB_RESETCONTENT = 0x0184,
    LB_SETHORIZONTALEXTENT = 0x0194,
    LB_GETHORIZONTALEXTENT = 0x0193,
    LB_GETTOPINDEX = 0x018E,
    LB_SETTOPINDEX = 0x0197,
    LB_INSERTSTRING = 0x0181,
    LB_DELETESTRING = 0x0182,
    LB_GETITEMDATA = 0x0199
}

回答1:


Made some sample code that might help - you can use as a guide.

The idea is to handle the TextChanged event of the ComboBox, and really just modify the ComboBox list items at that point. The example below will modify the list to add the current text (most important, as this will not change the text when you click the combobox) and any other items that meet the search criteria.

I don't think you need the code to re-initialize the list items when focus is lost, but left in there just in case.

    //contains a list of default items for the combobox items
    List<string> comboList = new List<string>();

    public Form1()
    {
        InitializeComponent();
        initComboList(); //initialize the defaults
        initCombobox(); //initialize the combobox list items
    }

    //fills the defaults for the combobox items
    private void initComboList()
    {
        comboList.Add("red");
        comboList.Add("blue");
        comboList.Add("green");
    }

    //initializes the combobox items
    private void initCombobox()
    {
        comboBox1.Items.Clear();
        foreach (string s in comboList)
            comboBox1.Items.Add(s);
    }

    //occurs when the text changes in the combobox
    private void comboBox1_TextChanged(object sender, EventArgs e)
    {
        string curtext = comboBox1.Text;
        insertIntoComboBox(curtext);   //insert the current text into combobox
        comboBox1.Select(curtext.Length, 0); //if you don't do this, the cursor goes back to index 0 :-(
    }

    //called whenever is desired to insert the current text into the combobox items
    private void insertIntoComboBox(string curtext)
    {
        comboBox1.Items.Clear();
        //only add the current text if it's not already in the list of defaults and not empty string
        if (comboList.Contains(curtext) == false && curtext.Length > 0)
            comboBox1.Items.Add(curtext);
        foreach (string s in comboList)
                comboBox1.Items.Add(s);
    }

    //called whenever combobox loses focus
    private void comboBox1_Leave(object sender, EventArgs e)
    {
        initCombobox();
    }


来源:https://stackoverflow.com/questions/16544663/how-can-i-prevent-auto-select-in-combobox-on-drop-down-except-for-exact-matches

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!