ListBox+WrapPanel 方向键导航 [英] ListBox+WrapPanel arrow key navigation
问题描述
我正在尝试实现相当于 WinForms ListView
的 View
属性设置为 View.List
.从视觉上看,以下工作正常.我的 Listbox
中的文件名从上到下,然后换行到新列.
I'm trying to achieve the equivalent of a WinForms ListView
with its View
property set to View.List
. Visually, the following works fine. The file names in my Listbox
go from top to bottom, and then wrap to a new column.
这是我正在使用的基本 XAML:
Here's the basic XAML I'm working with:
<ListBox Name="thelist"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"
Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
但是,默认的箭头键导航不会换行.如果选择了列中的最后一项,按向下箭头不会转到下一列的第一项.
However, default arrow key navigation does not wrap. If the last item in a column is selected, pressing the down arrow does not go to the first item of the next column.
我尝试像这样处理 KeyDown
事件:
I tried handling the KeyDown
event like this:
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();
}
}
}
这会产生我想要的从最后一列到下一列第一的行为,但也会在左右箭头处理中产生奇怪的现象.每当它使用向上/向下箭头从一列换行到下一列/上一列时,随后使用左箭头键或右箭头键将选择移动到发生换行之前选择的项目的左侧或右侧.
This produces the last-in-column to first-in-next-column behavior that I wanted, but also produces an oddity in the left and right arrow handling. Any time it wraps from one column to the next/previous using the up/down arrows, a single subsequent use of the left or right arrow key moves the selection to the left or right of the item that was selected just before the wrap occured.
假设列表由字符串0001"到0100"填充,每列有 10 个字符串.如果我使用向下箭头键从0010"转到0011",然后按向右箭头键,选择移动到0020",就在0010"的右侧.如果选择了0011"并且我使用向上箭头键将选择移动到0010",然后按下右箭头键将选择移动到0021"(在0011"的右侧,然后按下左侧箭头键将选择移动到0001".
Assume the list is filled with strings "0001" through "0100" with 10 strings per column. If I use the down arrow key to go from "0010" to "0011", then press the right arrow key, selection moves to "0020", just to the right of "0010". If "0011" is selected and I use the up arrow key to move selection to "0010", then a press of the right arrow keys moves selection to "0021" (to the right of "0011", and a press of the left arrow key moves selection to "0001".
任何帮助实现所需的列换行布局和箭头键导航将不胜感激.
Any help achieving the desired column-wrap layout and arrow key navigation would be appreciated.
(编辑移至我自己的答案,因为它在技术上是一个答案.)
(Edits moved to my own answer, since it technically is an answer.)
推荐答案
事实证明,当它在我处理 KeyDown
事件时回绕时,选择更改为正确的项目,但焦点是在旧物品上.
It turns out that when it wraps around in my handling of the KeyDown
event, selection changes to the correct item, but focus is on the old item.
这是更新后的 KeyDown
事件处理程序.由于绑定,Items
集合返回我的实际项目而不是 ListBoxItem
s,所以我必须在接近尾声时调用以获取实际的 ListBoxItem
我需要调用 Focus()
.通过交换 MoveCurrentToLast()
和 MoveCurrentToFirst()
的调用,可以实现从最后一项到第一项的包装,反之亦然.
Here is the updated KeyDown
eventhandler. Because of Binding, the Items
collection returns my actual items rather than ListBoxItem
s, so I have to do a call near the end to get the actual ListBoxItem
I need to call Focus()
on. Wrapping from last item to first and vice-versa can be achieved by swapping the calls of MoveCurrentToLast()
and 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();
}
}
}
这篇关于ListBox+WrapPanel 方向键导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!