2017-07-21 50 views
2

我有我的自定义组合框:导航在搜索WPF组合框

public class CustomComboBox : ComboBox 
{ 
    protected override void OnSelectionChanged(SelectionChangedEventArgs e) 
    { 
     // allow to go into items using up and down arrows without causing the text change 
     e.Handled = true; 
    } 
} 

和XAML为:

<Window> 
    <Grid> 
     <wpfApplication1:CustomComboBox IsEditable="True" 
        Width="200" 
        Height="25" 
        IsTextSearchEnabled="False" 
        StaysOpenOnEdit="True" 
        x:Name="cb" 
        PreviewTextInput="Cb_OnPreviewTextInput" 
        ItemsSource="{Binding Projects}" 
        Text="{Binding Text}" 
        SelectionChanged="Cb_OnSelectionChanged"> 
      <ComboBox.ItemsPanel> 
       <ItemsPanelTemplate> 
        <VirtualizingStackPanel /> 
       </ItemsPanelTemplate> 
      </ComboBox.ItemsPanel> 
     </wpfApplication1:CustomComboBox> 
    </Grid> 
</Window> 

代码窗口:

public partial class MainWindow : INotifyPropertyChanged 
{ 
    public ICollectionView Projects { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 

     ObservableCollection = new ObservableCollection<string>(Enumerable.Range(1, 1000).Select(i => $"Item {i}")); 

     Projects = CollectionViewSource.GetDefaultView(ObservableCollection); 
    } 

    private string _text; 
    public ObservableCollection<string> ObservableCollection { get; set; } 

    public string Text 
    { 
     get { return _text; } 
     set 
     { 
      if (_text != value) 
      { 
       _text = value; 
       OnPropertyChanged(); 

       Projects.Filter = f => 
       { 
        var search = Text.ToLower(); 
        var item = f.ToString().ToLower(); 

        return item.Contains(search); 
       }; 
      } 
     } 
    } 

    private void Cb_OnPreviewTextInput(object sender, TextCompositionEventArgs e) 
    { 
     cb.IsDropDownOpen = true; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

Cb_OnPreviewTextInput被称为我设置了IsDropdownOpen = true。在第一次尝试中(在输入第一个字母后),列表中的第一个项目被选中,我可以使用相关的箭头上下移动,插入符号仍然在TextBox

当我继续输入那个点时,我不能上下导航(1个时间点),此时整个ScrollViewer得到了重点,我只能到达底部或顶部,但不是1 1.我必须关闭弹出如按Escape键,然后重新打开,输入1个字符即可再次上/下。

我还注意到,按PageUp后第一个项目也被选中,所以我试图在代码中模仿,但没有运气。

任何人都知道在这里能做些什么,以便能够向上/向下导航和输入而没有问题?

我试过的东西:

protected override void OnPreviewKeyDown(KeyEventArgs e) 
{ 
    if (_popup != null && e.Key == Key.Up || e.Key == Key.Down) 
    { 
     Dispatcher.BeginInvoke(DispatcherPriority.Input, 
     new Action(() => 
     { 
      var c = _popup.Child; 
      var vs = c.GetChildOfType<VirtualizingStackPanel>(); 
      vs.PageUp(); 
      vs.Focus(); 
      Keyboard.Focus(vs); 
     })); 
    } 

    base.OnPreviewKeyDown(e); 
} 

但没有奏效。

回答

0

结束时写入一个新模板,其中包含ListView

加定制逻辑内OnPreviewKeyDown

if (e.Key == Key.Up || e.Key == Key.Down) 
{ 
    listView.Focus(); 
    listView.Items.MoveCurrentTo(listView.SelectedItem); 

    if (e.Key == Key.Up) 
     listView.Items.MoveCurrentToPrevious(); 
    else 
     listView.Items.MoveCurrentToNext(); 

    listView.SelectedItem = listView.Items.CurrentItem; 
    listView.ScrollIntoView(listView.Items.CurrentItem); 

    e.Handled = true; 

    return; 
} 

工作井;)