Навигация по вкладке ListView по столбцам, где ListViewItems являются сетками

У меня есть ListView, который представляет элементы горизонтально. Каждый элемент представляет собой сетку из 1 столбца. Внешний вид представляет собой сетку, в которой количество столбцов является динамическим. Все это работает и выглядит так, как я хочу, за исключением навигации по вкладкам. У меня есть KeyboardNavigation.TabNavigation="Continue", установленный в ListView, и для KeyboardNavigation.IsTabStop установлено значение false в ItemContainerStyle, что позволяет мне просматривать каждую строку в элементе, затем переходить к следующему элементу и т. д. Однако я хотел бы перейти на вкладку с первого строку в первом элементе в первую строку во втором элементе и т. д., затем в следующую строку.

Ex.

Item1Row1 -> Item2Row1 -> Item3Row1 -> ...

Item1Row2 -> Item2Row2 -> Item3Row2 -> ...

У меня есть индексы вкладок, настроенные для элементов управления в каждой ячейке (которые я проверил, верны), но я не могу понять, какие настройки мне нужны, чтобы включить индексы вкладок в ListView/ListViewItems. Любая помощь будет принята с благодарностью. Вот xaml...

<ListView VerticalAlignment="Top" Background="Transparent" BorderThickness="0" KeyboardNavigation.TabNavigation="Continue" ItemsSource="{Binding RawProductDataItemViewModels}">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="False"/>
            <Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid VerticalAlignment="Top" Margin="2.5,0,2.5,0">
                <Grid.RowDefinitions>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                    <RowDefinition SharedSizeGroup="ButtonAndGridGroup"/>
                </Grid.RowDefinitions>

                <TextBlock Margin="5,4,0,0" Grid.Row="0">
                        <TextBlock.Text>
                            <MultiBinding StringFormat="Lane #{0}">
                                <Binding Path="Lane"/>
                            </MultiBinding>
                        </TextBlock.Text>
                </TextBlock>
                <TextBox Grid.Row="1" Margin="0,4,0,0" Width="75" Text="{Binding RollNumber, StringFormat='{}{0:#####-#}', TargetNullValue=''}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=1}"/>
                <TextBox Grid.Row="2" Margin="0,4,0,0" Width="75" Text="{Binding PCode}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=2}"/>
                <TextBox Grid.Row="3" Margin="0,4,0,0" Width="75" Text="{Binding RollWidth}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=3}"/>
                <TextBox Grid.Row="4" Margin="0,4,0,0" Width="75" Text="{Binding RollWeight}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=4}"/>
                <TextBox Grid.Row="5" Margin="0,4,0,0" Width="75" Text="{Binding GrossWeight}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=5}"/>
                <TextBox Grid.Row="6" Margin="0,4,0,0" Width="75" Text="{Binding BurnWeight}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=6}"/>
                <TextBox Grid.Row="7" Margin="0,4,0,0" Width="75" Text="{Binding SqFtWeight}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=7}"/>
                <TextBox Grid.Row="8" Margin="0,4,0,0" Width="75" Text="{Binding Cure}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=8}"/>
                <TextBox Grid.Row="9" Margin="0,4,0,0" Width="75" Text="{Binding Rigidity}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=9}"/>
                <TextBox Grid.Row="10" Margin="0,4,0,0" Width="75" Text="{Binding Telescope}"
                            TabIndex="{Binding Lane, Converter={StaticResource IntegersTo2DIndex}, ConverterParameter=10}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

person scuba88    schedule 29.08.2012    source источник


Ответы (1)


Я решил обработать это в коде позади. Я удалил индексы вкладок в текстовых полях в xaml. Решение некрасивое, но, на мой взгляд, оно лучше, чем удаление списка и жесткое кодирование всех дорожек, чтобы я мог использовать индексы вкладок.

Предварительный просмотр обработчика нажатия клавиши в ListView:

private void LanesListView_PreviewKeyDown(object sender, KeyEventArgs e)
{
    UIElement uie = e.OriginalSource as UIElement;

    // 'Ctrl + Tab' or 'Shift + Enter' (Reverse Tab)
    if ((e.Key == Key.Tab || e.Key == Key.Return) &&
        (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift &&
         uie != null)
    {
        MoveFocusPrevious(uie, (UIElement)sender);

        e.Handled = true;
    }
    else if ((e.Key == Key.Tab || e.Key == Key.Return) && uie != null)
    {
        // Normal 'Enter' or 'Tab' key click
        MoveFocusNext(uie, (UIElement)sender);

        e.Handled = true;
    }
}

Методы перемещения фокуса:

private void MoveFocusNext(UIElement uie, UIElement sender)
{
    if(!uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right)))
    {
        uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); // Move Down
        uie = (UIElement)Keyboard.FocusedElement;
        MoveFocusToFirst(uie, sender); // Move to to first
    }
}

private void MoveFocusPrevious(UIElement uie, UIElement sender)
{
    if (!uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Left)))
    {
        uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous)); // Move Up
        uie = (UIElement)Keyboard.FocusedElement;
        MoveFocusToLast(uie, sender); // Move focus to last
    }
}

private void MoveFocusToLast(UIElement uie, UIElement sender)
{
    bool isLast = false;

    // Move right until hitting last item
    while(!isLast)
    {
        // If Focus cannot be moved, it is last item.
        isLast = !uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
        uie = (UIElement)Keyboard.FocusedElement;
    }
}

private void MoveFocusToFirst(UIElement uie, UIElement sender)
{
    bool isFirst = false;

    // Move left until hitting last item
    while (!isFirst)
    {
        // If Focus cannot be moved, it is last item.
        isFirst = !uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Left)); 
        uie = (UIElement)Keyboard.FocusedElement; 
    }
}
person scuba88    schedule 14.09.2012