Ограниченное автозаполнение в поле со списком

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

В настоящее время я использую этот код:

    protected virtual void comboBoxAutoComplete_KeyPress(object sender, KeyPressEventArgs e) {
        if (Char.IsControl(e.KeyChar)) {
            //let it go if it's a control char such as escape, tab, backspace, enter...
            return;
        }
        ComboBox box = ((ComboBox)sender);

        //must get the selected portion only. Otherwise, we append the e.KeyChar to the AutoSuggested value (i.e. we'd never get anywhere)
        string nonSelected = box.Text.Substring(0, box.Text.Length - box.SelectionLength);

        string text = nonSelected + e.KeyChar;
        bool matched = false;
        for (int i = 0; i < box.Items.Count; i++) {
            if (((DataRowView)box.Items[i])[box.DisplayMember].ToString().StartsWith(text, true, null)) {
                //box.SelectedItem = box.Items[i];
                matched = true;
                break;
            }
        }

        //toggle the matched bool because if we set handled to true, it precent's input, and we don't want to prevent
        //input if it's matched.
        e.Handled = !matched;
    }

Он хорошо работает для любого поля со списком, которое использует данные, привязанные к базе данных, и нечувствительно к регистру. Однако, если пользователь вводит что-то в неправильном регистре, а затем выходит из поля со списком, выбранное значение поля со списком по-прежнему равно -1 (или каково было предыдущее значение). Это не то поведение, которое я хочу, я хочу, чтобы оно установило значение, которое в настоящее время является лучшим предположением о том, что связывает пользователь, то есть параметр автозаполнения.

Я пробовал это, если вы видите закомментированную строку в цикле for. Это не работает.
Это происходит примерно так:
У меня есть поле "Аренда" со значением 53
Я набираю 'r'
Я получаю поле со списком результатов 'rRent'
.SelectedValue возвращает -1

Что он сейчас делает:
У меня есть поле "Аренда" со значением 53
Я набираю "r"
Автозаполнение предлагает "аренда"
Это правильное значение поэтому я иду дальше, и поле со списком теряет фокус
Поле со списком отображает "аренда"
поле со списком.SelectedValue return -1

Что я хочу:
У меня есть поле "Аренда" со значением 53
Я набираю "r"
Поле со списком теряет фокус, оно заполняет "аренда" (даже хотя это не в правильном регистре [уже делает это])
combobox.SelectedValue теперь должен возвращать 53

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

У кого-нибудь есть предложения по устранению этой ошибки?


person Malfist    schedule 15.05.2009    source источник
comment
Почему бы вам не очистить текст, прежде чем пытаться добавить к нему совпадение?   -  person TheTXI    schedule 15.05.2009
comment
Я не пытаюсь добавить к нему совпадение. Я только что обновил вопрос, чтобы в нем было больше деталей.   -  person Malfist    schedule 15.05.2009


Ответы (2)


Может быть, это неправильное дерево, но вы пытались просто включить автозаполнение в поле со списком?

comboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
comboBox.AutoCompleteSource = AutoCompleteSource.ListItems;
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;        

Последняя строка ограничит ввод элементами в списке.

person Thies    schedule 15.05.2009
comment
Да. Но это не мешает пользователям вводить новые параметры. - person Malfist; 15.05.2009
comment
Извините, забыл один важный момент; установите для DropDownStyle значение DropDownList - person Thies; 15.05.2009
comment
DropDownList означает, что вы не можете печатать. Это приведет вас к первому элементу с этим персонажем, но не дальше. - person Chris Pfohl; 09.02.2012

Похоже, у меня нет другого выбора, кроме как сделать это в событии LeaveFocus, это решает проблему:

    protected void autocomplete_LeaveFocus(object sender, EventArgs e) {
        ComboBox box = ((ComboBox)sender);
        String selectedValueText = box.Text;

        //search and locate the selected value case insensitivly and set it as the selected value
        for (int i = 0; i < box.Items.Count; i++) {
            if (((DataRowView)box.Items[i])[box.DisplayMember].ToString().Equals(selectedValueText, StringComparison.InvariantCultureIgnoreCase)) {
                box.SelectedItem = box.Items[i];
                break;
            }
        }
    }
person Malfist    schedule 15.05.2009