带有IsEditable =“True”的WPF ComboBox - 如何指示未找到匹配项?

时间:2011-01-05 22:27:27

标签: wpf validation combobox

使用以下简单文本框作为示例:

<ComboBox IsEditable="True" SelectedItem="{Binding}">
    <ComboBoxItem>Angus/ComboBoxItem>
    <ComboBoxItem>Jane</ComboBoxItem>
    <ComboBoxItem>Steve</ComboBoxItem>
</ComboBox>

我想允许用户通过输入名称来查找他们的选择,因此我将 IsEditable 设置为等于true。绑定到 SelectedItem 的属性的可接受值是列表中的任何一个选项,或者没有选择( null )。问题是,如果有人输入不在列表中的名称,则默认情况下没有错误指示。

例如:用户可以键入“Bob”,导致 SelectedItem 属性 null ,但没有意识到Bob在列表中不存在。相反,我想在ComboBox的 Text 属性不是 null 或空的时候提供视觉指示,并且 SelectedItem null < / em>,并阻止他们再输入?

我最初的想法是自定义验证规则,但我不知道如何访问组合框的Text和SelectedItem属性。

3 个答案:

答案 0 :(得分:3)

作为初学者,您可能希望让用户看到他们是否输入了其中一个可用选项。

1)在线搜索“autocomplete 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>

上面的代码片段是提供您正在寻找的“视觉指示”的一种原始方式。如果用户键入“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;
        }
    }

在这里,一旦我们检测到没有组合框项目以文本框中的文本开头,我们就不会让用户继续输入。我们删除添加的字符并等待另一个字符。

答案 1 :(得分:2)

此解决方案基于user1234567的答案,并进行了一些更改。它不是搜索项目列表,而是简单地检查ComboBox的SelectedIndex值是否> = 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;
        }
    }
}

答案 2 :(得分:1)

这是一个很好的解决方案,直到你在组合框中有很多记录。我会这样做:

在文件顶部声明这个

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

除非绑定继续向组合框添加记录,否则我认为是更有效的查找