Отключить табуляцию между столбцами в таблице данных WPF

У меня есть сетка данных WPF Toolkit с несколькими столбцами. Я пытаюсь получить поведение, при котором вы можете перейти в сетку с помощью вкладки, а затем снова выйти с помощью одной вкладки. Например. Я не хочу, чтобы табуляция проходила по всем столбцам или ячейкам сетки, только один раз и один раз вышла.

Есть ли простое решение? Я попытался установить для TabNavigation значение Once, а также отключить TabStop (не показано в коде ниже) и установить для TabNavigation в столбцах значение None, но безуспешно.

Что-то мне не хватает или мне нужно обрабатывать клавишу Tab в коде?

        <my:DataGrid Name="datagrid"
                     AutoGenerateColumns="False" IsReadOnly="True"
                     CanUserAddRows="False" CanUserDeleteRows="False"
                     Background="White"
                     KeyboardNavigation.TabNavigation="Once">
            <my:DataGrid.Columns>
                <my:DataGridTextColumn x:Name="ID" Header="ID" Width="1*" ></my:DataGridTextColumn>
                <my:DataGridTextColumn x:Name="Ticker" Header="Ticker" Width="1*" KeyboardNavigation.TabNavigation="None"></my:DataGridTextColumn>
                <my:DataGridTextColumn x:Name="OfficialName" Header="Name" Width="3*" KeyboardNavigation.TabNavigation="None"></my:DataGridTextColumn>
            </my:DataGrid.Columns>
        </my:DataGrid>

person Thies    schedule 21.01.2010    source источник


Ответы (3)


Интересно, что установка KeyboardNavigation непосредственно для DataGridTextColumn не работает. Альтернатива, которая должна работать, - это настроить стиль DataGridCell.

<toolkit:DataGrid.CellStyle>
    <Style TargetType="{x:Type toolkit:DataGridCell}">
        <Setter Property="KeyboardNavigation.IsTabStop"
                Value="False" />
        <Style.Triggers>
            <Trigger Property="IsSelected"
                     Value="True">
                <Setter Property="KeyboardNavigation.IsTabStop"
                        Value="True" />
            </Trigger>
        </Style.Triggers>
    </Style>
</toolkit:DataGrid.CellStyle>

Присоединение этого к DataGrid гарантирует, что ячейка будет только TabStop, если она уже выбрана. Однако, если вы выбираете полные строки и не установили SelectionUnit = "Cell" в DataGrid, он все равно будет циклически проходить через каждый столбец текущей выбранной строки.

Вместо этого мы можем создать несколько стилей ячеек как ресурсы в DataGrid:

<toolkit:DataGrid.Resources>

    <Style  x:Key="SelectableCellStyle"
            TargetType="{x:Type toolkit:DataGridCell}">
        <Setter Property="KeyboardNavigation.IsTabStop"
                Value="False" />
        <Style.Triggers>
            <Trigger Property="IsSelected"
                     Value="True">
                <Setter Property="KeyboardNavigation.IsTabStop"
                        Value="True" />
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style TargetType="{x:Type toolkit:DataGridCell}">
        <Setter Property="KeyboardNavigation.IsTabStop"
                Value="False" />
    </Style>

</toolkit:DataGrid.Resources>

Теперь у нас есть стиль, применяемый ко всем DataGridCell по умолчанию и отключивший TabStop, и стиль с клавишами, который позволяет выбирать, когда выбрана ячейка (или вся строка). Применение этого стиля только к одному столбцу даст нам тот же эффект одиночной вкладки, позволяя выбрать всю строку и все ее столбцы.

 <my:DataGridTextColumn x:Name="ID" Header="ID" Width="1*" CellStyle={StaticResource  SelectableCellStyle}"/>

Это также останавливает переход в DataGrid, если ничего не выбрано, что может быть предпочтительным или нет в зависимости от ситуации, в которой вы его используете.

person rmoore    schedule 21.01.2010

Спасибо, rmoore. Чтобы отключить табуляцию для столбцов, я взял ваш ответ и немного изменил его;

     <my:DataGrid Name="datagrid" 
                 AutoGenerateColumns="False" IsReadOnly="True" 
                 CanUserAddRows="False" CanUserDeleteRows="False" 
                 Background="White" 
                 KeyboardNavigation.TabNavigation="Once"
                 SelectionUnit="FullRow"> 
        <my:DataGrid.Columns> 
            <my:DataGridTextColumn x:Name="ID" Header="ID" Width="1*" ></my:DataGridTextColumn> 
            <my:DataGridTextColumn x:Name="Ticker" Header="Ticker" Width="1*">
                    <my:DataGridTextColumn.CellStyle>
                        <Style TargetType="{x:Type my:DataGridCell}">
                            <Setter Property="KeyboardNavigation.IsTabStop" Value="False"></Setter>
                        </Style>
                    </my:DataGridTextColumn.CellStyle>
            </my:DataGridTextColumn> 

            <my:DataGridTextColumn x:Name="OfficialName" Header="Name" Width="3*">
                  <my:DataGridTextColumn.CellStyle>
                        <Style TargetType="{x:Type my:DataGridCell}">
                            <Setter Property="KeyboardNavigation.IsTabStop" Value="False"></Setter>
                        </Style>
                  </my:DataGridTextColumn.CellStyle>
            </my:DataGridTextColumn> 
        </my:DataGrid.Columns> 
    </my:DataGrid>

Итак, хитрости;

  1. SelectionUnit = "FullRow" заставляет графический интерфейс выглядеть так, как будто вы выполняете действия по одной строке за раз (как я и хотел).
  2. Добавление CellStyle в столбцы, в которых я хочу отключить TabStop (но не включая его в те, в которых я хотел бы остановиться), позволило мне контролировать, в какие ячейки будет переходить эта клавиша табуляции. - KeyboardNavigation.TabNavigation не действует при определении для столбцов.
person Thies    schedule 22.01.2010

Я знаю, что это действительно старый вопрос, но я публикую его здесь, если он кому-то поможет. Хотя принятый ответ хорош, я не верю, что он охватывает случай, когда в том же окне есть другой элемент управления, и вы хотели бы перейти в DataGrid из этого элемента управления. Кроме того, вам может потребоваться поведение, описанное в исходном вопросе (одна вкладка на входе, одна табуляция без табуляции, без перехода по ячейкам / столбцам). Это решение направлено на достижение этой цели.

Примечание. Это решение предполагает, что вы хотите, чтобы ваш SelectionUnit был FullRow в вашем DataGrid.

Во-первых, вот Style, который нужно применить к DataGrid:

<DataGrid.Resources>
    <Style TargetType="DataGridRow">
        <Style.Setters>
            <Setter Property="Focusable" Value="True"/>
        </Style.Setters>
        <Style.Triggers>
            <Trigger Property="IsFocused" Value="True">
                <Setter Property="IsSelected" Value="True"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style TargetType="DataGridCell">
        <Style.Setters>
            <Setter Property="Focusable" Value="False"/>
        </Style.Setters>
    </Style>
</DataGrid.Resources>

Этот стиль позволяет сосредоточиться на строках, но предотвращает фокусировку на отдельных ячейках, что сохраняет фокус согласованным с SelectionUnit из FullRow. Триггер, установленный внутри этого стиля, является необязательным - он нужен только в том случае, если вы хотите автоматически выбирать строку, когда она получает фокус.

В моем случае мне нужно было поведение одиночной вкладки при вводе / выводе, поэтому я также установил свойство KeyboardNavigation.TabNavigation в моем DataGrid = "Once".

<DataGrid SelectionUnit="FullRow" KeyboardNavigation.TabNavigation="Once">

При таком подходе я все еще могу использовать клавиши со стрелками вверх / вниз для циклического перехода по строкам после того, как DataGrid получит фокус, но я все еще могу быстро перейти на вкладку, если я хочу переместить фокус на следующий элемент управления в порядке табуляции.

person Mash    schedule 08.06.2019
comment
Для меня это не совсем сработало, но близко! Когда в DataGrid более одной строки, при переходе в DataGrid в первый раз выбирается первая строка, а следующая вкладка выводится из DataGrid. Но затем, если вы выберете вторую строку и вкладку достаточно, чтобы вернуться к DataGrid, она повторно выберет ПЕРВУЮ строку. - person jep; 07.10.2019