ListBox + WrapPanel箭头键导航 [英] ListBox+WrapPanel arrow key navigation

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

问题描述

我正在尝试将其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 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天全站免登陆