Навигация с помощью клавиш со стрелками ListBox + WrapPanel - PullRequest
5 голосов
/ 25 сентября 2008

Я пытаюсь получить эквивалент WinForms ListView со свойством View, установленным на View.List. Визуально следующее работает отлично. Имена файлов в моем 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" по "0100" с 10 строками на столбец. Если я использую клавишу со стрелкой вниз, чтобы перейти от «0010» к «0011», то нажмите клавишу со стрелкой вправо, выбор переместится на «0020», справа от «0010». Если выбрано «0011» и я использую клавишу со стрелкой вверх, чтобы переместить выделение на «0010», то нажатие клавиш со стрелками вправо перемещает выделение на «0021» (справа от «0011» и нажатие влево клавиша со стрелкой перемещает выделение на «0001».

Буду признателен за любую помощь в достижении желаемого макета обтекания столбцов и навигации по клавишам со стрелками.

(Изменения перенесены в мой собственный ответ, поскольку технически это ответ.)

Ответы [ 2 ]

8 голосов
/ 26 сентября 2008

Оказывается, что при обработке события KeyDown выбор изменяется на правильный элемент, но фокус на старом элементе.

Вот обновленный обработчик событий KeyDown. Из-за Binding коллекция Items возвращает мои фактические предметы, а не ListBoxItem s, поэтому я должен сделать звонок ближе к концу, чтобы получить фактический 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();
        }
    }
}
4 голосов
/ 06 ноября 2008

Вы должны быть в состоянии сделать это без прослушивателя событий, используя KeyboardNavigation.DirectionalNavigation, например,

<ListBox Name="thelist"
         IsSynchronizedWithCurrentItem="True"
         ItemsSource="{Binding}"
         ScrollViewer.VerticalScrollBarVisibility="Disabled"
         KeyboardNavigation.DirectionalNavigation="Cycle">
...