ListBox + WrapPanel箭头键导航 [英] ListBox+WrapPanel arrow key navigation
问题描述
我正在尝试将其View
属性设置为View.List
的WinForms ListView
等效.在视觉上,以下工作正常. 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
,因此我必须在末尾进行调用以获取需要调用Focus()
的实际ListBoxItem
.通过交换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屋!