WPF ComboBox с IsEditable= "True" - как я могу указать, что совпадение не найдено?
используя в качестве примера следующее простое текстовое поле:
<ComboBox IsEditable="True" SelectedItem="{Binding}">
<ComboBoxItem>Angus/ComboBoxItem>
<ComboBoxItem>Jane</ComboBoxItem>
<ComboBoxItem>Steve</ComboBoxItem>
</ComboBox>
Я хотел бы позволить пользователю найти их выбор, введя имя, поэтому я установил IsEditable равно true. Допустимые значения для свойства, связанного с SelectedItem являются ли какие-либо из параметров в списке или нет выбора (null). Проблема в том, что по умолчанию нет указания на ошибку в случае, если кто-то вводит имя, которого нет в список.
например: пользователь может ввести "Bob", вызывая SelectedItem свойства null, но не понимаю, что Боб не существует в списке. Вместо этого я хотел бы предоставить визуальную индикацию, как только Combobox's текст собственность-это не null или пустой и SelectedItem is null, и остановить их от ввода больше?
моя первоначальная мысль была пользовательским правилом проверки, но я не знаю, как получить доступ как к тексту, так и к свойствам SelectedItem combobox.
3 ответов
в качестве стартера вы можете позволить пользователю увидеть, вводят ли они один из доступных вариантов.
1) Поиск "автозаполнение combobox" онлайн.
2) Проверьте это:
http://weblogs.asp.net/okloeten/archive/2007/11/12/5088649.aspx
http://www.codeproject.com/KB/WPF/WPFCustomComboBox.aspx
3) также попробуйте следующее:
<ComboBox IsEditable="true" TextSearch.TextPath="Content">
<ComboBoxItem Content="Hello"/>
<ComboBoxItem Content="World"/>
</ComboBox>
приведенный выше фрагмент кода является primite способ обеспечить "визуальную индикацию", которую вы ищете. Если пользователь вводит "h", то в текстовом поле ввода появится "hello". Однако это само по себе не будет иметь механизма, чтобы остановить пользователя от ввода незаконного символа.
4) это более продвинутый вариант:
<ComboBox Name="myComboBox" IsEditable="true" KeyUp="myComboBox_KeyUp">
<ComboBoxItem Content="Hello"/>
<ComboBoxItem Content="World"/>
<ComboBoxItem Content="WPF"/>
<ComboBoxItem Content="ComboBox"/>
</ComboBox>
код:
private void myComboBox_KeyUp(object sender, KeyEventArgs e)
{
// Get the textbox part of the combobox
TextBox textBox = myComboBox.Template.FindName("PART_EditableTextBox", myComboBox) as TextBox;
// holds the list of combobox items as strings
List<String> items = new List<String>();
// indicates whether the new character added should be removed
bool shouldRemove = true;
for (int i = 0; i < myComboBox.Items.Count; i++)
{
items.Add(((ComboBoxItem)myComboBox.Items.GetItemAt(i)).Content.ToString());
}
for (int i = 0; i < items.Count; i++)
{
// legal character input
if(textBox.Text != "" && items.ElementAt(i).StartsWith(textBox.Text))
{
shouldRemove = false;
break;
}
}
// illegal character input
if (textBox.Text != "" && shouldRemove)
{
textBox.Text = textBox.Text.Remove(textBox.Text.Length - 1);
textBox.CaretIndex = textBox.Text.Length;
}
}
здесь мы не позволяем пользователю продолжать вводить, как только мы обнаружим, что ни один элемент combobox не начинается с текста в текстовом поле. Мы удаляем персонаж добавлен и ждет другого персонажа.
это решение основано на ответе user1234567 с несколькими изменениями. Вместо поиска списка элементов он просто проверяет SelectedIndex ComboBox на значение >= 0, чтобы увидеть, было ли найдено совпадение, и это решает проблему RB о удержании ключа, вставляющего более одного символа. Он также добавляет звуковую обратную связь, когда он отвергает символы.
private int _lastMatchLength = 0;
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
_lastMatchLength = 0;
}
private void myComboBox_KeyUp(object sender, KeyEventArgs e)
{
ComboBox cBox = sender as ComboBox;
TextBox tb = cBox.Template.FindName("PART_EditableTextBox", cBox) as TextBox;
if (tb != null)
{
if (cBox.SelectedIndex >= 0)
{
_lastMatchLength = tb.SelectionStart;
}
else if (tb.Text.Length == 0)
{
_lastMatchLength = 0;
}
else
{
System.Media.SystemSounds.Beep.Play();
tb.Text = tb.Text.Substring(0, _lastMatchLength);
tb.CaretIndex = tb.Text.Length;
}
}
}
Это хорошее решение, пока у вас много записей в поле со списком. Я бы сделал это так:
объявить это в верхней части файла
List<String> items = new List<String>();
private void myComboBox_KeyUp(object sender, KeyEventArgs e)
{
TextBox textBox = myComboBox.Template.FindName("PART_EditableTextBox", myComboBox) as TextBox;
// indicates whether the new character added should be removed
bool shouldRemove = true;
// this way you don't fill the list for every char typed
if(items.Count <= 0)
{
for (int i = 0; i < myComboBox.Items.Count; i++)
{
items.Add(((ComboBoxItem)myComboBox.Items.GetItemAt(i)).Content.ToString());
}
}
// then look in the list
for (int i = 0; i < items.Count; i++)
{
// legal character input
if(textBox.Text != "" && items.ElementAt(i).StartsWith(textBox.Text))
{
shouldRemove = false;
break;
}
}
// illegal character input
if (textBox.Text != "" && shouldRemove)
{
textBox.Text = textBox.Text.Remove(textBox.Text.Length - 1);
textBox.CaretIndex = textBox.Text.Length;
}
}
если привязка не продолжает добавлять записи в поле со списком, я думаю, что это более эффективный поиск