Список + панель-оболочка навигация по клавишам со стрелками

StackOverflow https://stackoverflow.com/questions/134068

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

<ListBox Name="thelist"
         IsSynchronizedWithCurrentItem="True"
         ItemsSource="{Binding}"
         ScrollViewer.VerticalScrollBarVisibility="Disabled"
         KeyboardNavigation.DirectionalNavigation="Cycle">
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top