我有自定义的ComboBox:
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 as:
<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 :(得分: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;
}
运作良好;)