ListBox + WrapPanel箭头键导航
题
我正在尝试使用 View
属性设置为 View.List
来实现WinForms ListView
的等价物。在视觉上,以下工作正常。我的 Listbox
中的文件名从上到下,然后换行到新列。
这是我正在使用的基本XAML:
<ListBox Name="thelist"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"
Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
但是,默认箭头键导航不会换行。如果选择了列中的最后一项,则按向下箭头不会转到下一列的第一项。
我尝试像这样处理 KeyDown
事件:
private void thelist_KeyDown( object sender, KeyEventArgs e ) {
if ( object.ReferenceEquals( sender, thelist ) ) {
if ( e.Key == Key.Down ) {
e.Handled = true;
thelist.Items.MoveCurrentToNext();
}
if ( e.Key == Key.Up ) {
e.Handled = true;
thelist.Items.MoveCurrentToPrevious();
}
}
}
这会产生我想要的最后一列到下一列的行为,但在左右箭头处理中也会产生奇怪的现象。每当使用向上/向下箭头从一列包裹到下一个/上一个列时,单个后续使用左或右箭头键将选择移动到刚好在换行之前选择的项目的左侧或右侧。
假设列表中填充了字符串“0001”和“0001”。通过“0100”每列10个字符串。如果我使用向下箭头键从“0010”转到“0010”。然后按下右箭头键,选择移动到“0020”,恰好在“0010”的右边。如果“0011”,如果选择并且我使用向上箭头键将选择移动到“0010”,则按下右箭头键将选择移动到“0021”。 (在“0011”的右侧,按下左箭头键将选择移动到“0001”。
任何帮助实现所需的柱包布局和箭头键导航都将不胜感激。
(编辑转到我自己的答案,因为它在技术上是一个答案。)
解决方案
事实证明,当我处理 KeyDown
事件时,选择会更改为正确的项目,但焦点是旧项目。
这是更新的 KeyDown
事件处理程序。由于Binding, Items
集合返回我的实际项而不是 ListBoxItem
,所以我必须在结尾附近进行调用以获取实际的 ListBoxItem
我需要调用 Focus()
。通过交换 MoveCurrentToLast()
和 MoveCurrentToFirst()
的调用,可以实现从最后一项到第一项的反馈,反之亦然。
private void thelist_KeyDown( object sender, KeyEventArgs e ) {
if ( object.ReferenceEquals( sender, thelist ) ) {
if ( thelist.Items.Count > 0 ) {
switch ( e.Key ) {
case Key.Down:
if ( !thelist.Items.MoveCurrentToNext() ) {
thelist.Items.MoveCurrentToLast();
}
break;
case Key.Up:
if ( !thelist.Items.MoveCurrentToPrevious() ) {
thelist.Items.MoveCurrentToFirst();
}
break;
default:
return;
}
e.Handled = true;
ListBoxItem lbi = (ListBoxItem) thelist.ItemContainerGenerator.ContainerFromItem( thelist.SelectedItem );
lbi.Focus();
}
}
}
其他提示
你应该能够在没有事件监听器的情况下使用KeyboardNavigation.DirectionalNavigation,例如。
<ListBox Name="thelist"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
KeyboardNavigation.DirectionalNavigation="Cycle">