Подтвердить что ты не робот

Переопределить Winforms ComboBox Autocomplete Предложить правило

Я пытаюсь изменить поведение пакета Windows.Forms ComboBox, чтобы выпадающий список автозаполнения отображал элементы в соответствии с указанными правилами.

По умолчанию, если вы используете AutoComplete в ComboBox, следующее правило: "string s включено в drop down if (s.StartsWith(userEnteredTextInTheComboBox))" Все, что меня действительно интересует, заключается в замене нового правила для нынешнего, но я не могу найти способ добраться до него. (В частности, я предпочел бы s.Contains вместо s.StartsWith.)

Я могу объединить неуклюжие решения, используя два элемента управления вместо одного, но я действительно был бы более счастлив с тем, который действительно делает то, что я хочу.

Обновление: я нашел по существу тот же вопрос после некоторого поиска. Ответ, поставленный там, предполагает, что использование двух элементов управления для "подделки" - это путь.

4b9b3361

Ответ 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());
}