ListBox+WrapPanel 方向键导航 [英] ListBox+WrapPanel arrow key navigation

查看:17
本文介绍了ListBox+WrapPanel 方向键导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现相当于 WinForms ListViewView 属性设置为 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 集合返回我的实际项目而不是 ListBoxItems,所以我必须在接近尾声时调用以获取实际的 ListBoxItem 我需要调用 Focus().通过交换 MoveCurrentToLast()MoveCurrentToFirst() 的调用,可以实现从最后一项到第一项的包装,反之亦然.

Here is the updated KeyDown eventhandler. Because of Binding, the Items collection returns my actual items rather than ListBoxItems, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆