2011-01-05 34 views
6

使用下面简单的文本框为例:带有IsEditable =“True”的WPF组合框 - 如何指示未找到匹配项?

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

我想允许用户通过键入姓名来找到自己的选择,所以我已经设置IsEditable等于true。与SelectedItem绑定的属性的可接受值是列表中的任何一个选项,或者没有选择(null)。问题是,如果某人键入的名字不在列表中,则默认情况下没有错误提示。

例如:用户可以输入“鲍勃”,引起的SelectedItem属性为,但没有意识到,鲍勃没有在列表中存在。相反,我想尽快提供一个视觉指示组合框的文本财产或空的SelectedItem,并从输入任何更多的阻止他们?

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

+0

小费我的WPF老师的过程中重复数十次:在WPF,你不应该使用的SelectedItem明确。这是收集意见的目的。 – 2011-01-05 22:34:36

回答

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> 

上面代码段是一个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; 
     } 
    } 

在这里,我们不会让用户继续输入中,一旦我们发现,没有组合框项目从文本框中的文本开始。我们删除添加的角色并等待另一个角色。

+0

此代码中存在一个错误 - 可以按住一个键,并且写入的代码只会删除最后一个字符。 (例如,如果用户按下'f'键直到5'f被输入,则4将被附加到文本中)。尽管如此,我还没有找到解决方案。 – 2014-08-06 10:59:18

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

除非绑定继续添加记录到组合框,我认为这是一个更有效的查找

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