ListBox + WrapPanel навигация по клавишам со стрелками

Я пытаюсь получить эквивалент 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».

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
8 082
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

Отлично, это мне очень помогло. ;)

Inferis 16.03.2009 23:55

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

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

Другие вопросы по теме