【问题标题】:WPF ComboBox with IsEditable="True" - How can I indicate that no match was found?带有 IsEditable="True" 的 WPF ComboBox - 如何指示未找到匹配项?
【发布时间】:2015-05-05 02:10:43
【问题描述】:

以下面的简单文本框为例:

<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 或为空且 SelectedItemnull,然后阻止他们再输入?

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

【问题讨论】:

  • 我的 WPF 老师在课程中重复了数十次的提示:在 WPF 中,您永远不应该明确使用 SelectedItem。这就是集合视图的用途。

标签: wpf validation combobox


【解决方案1】:

作为初学者,您可能希望让用户查看他们是否正在输入可用选项之一。

1) 在线搜索“自动完成组合框”。

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>

上面的代码 sn-p 是提供您正在寻找的“视觉指示”的一种基本方式。如果用户输入“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;
        }
    }

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

【讨论】:

  • 这段代码有一个错误 - 可以按住一个键,而编写的代码只会删除最后一个字符。 (例如,如果用户按住 f 键直到输入了 5 个 'f',则 4 将附加到文本中)。不过我还没有找到解决方案。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    在文件顶部声明

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

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

    【讨论】:

      猜你喜欢
      • 2010-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 2014-07-29
      • 1970-01-01
      • 2020-09-05
      • 2016-11-26
      相关资源
      最近更新 更多