在WPF数据网格中禁用列之间的Tab键切换

15

我有一个带有多个列的WPF Toolkit数据网格。 我正在尝试实现一种行为,即您可以使用tab键进入网格,然后再次使用单个tab键将其退出。 例如,我不想通过网格的所有列或单元格进行tab键切换,只需进入一次,再次退出一次。

是否有简单的解决方案?我尝试将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>

https://dev59.com/JEfRa4cB1Zd3GeqP-JJ9#1707920 - Bermo
3个回答

21

有趣的是,直接在DataGridTextColumn上设置KeyboardNavigation无效。一个可行的替代方案是设置一个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。但是,如果您选择整行并且在DataGrid上没有设置SelectionUnit="Cell",它仍将循环遍历当前所选行的每列。

相反,我们可以在DataGrid中创建多个CellStyle作为资源:

<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>

现在,默认情况下所有DataGridCells都应用了样式,并关闭了TabStop,同时有一个带键的样式,在单元格(或整个行)被选定时允许选择。仅将此样式应用于单个列将给我们相同的单个选项卡效果,同时允许选择整个行及其所有列。

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

如果没有选中任何内容,这也会停止在数据网格中制表,这可能取决于您使用它的情况是否更为优选。


10

谢谢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" 设置后,GUI 界面看起来像你是一次处理一行(正如我所期望的)。
  2. 通过为我想要禁用 TabStop 的列添加 CellStyle(但不包括那些我想停在其中的列),我可以控制 Tab 键导航到哪些单元格中。- 当定义在列上时,KeyboardNavigation.TabNavigation 没有影响。

2
我知道这是一个非常老的问题,但我在这里发布它以帮助他人。虽然被接受的答案很好,但我认为它没有涵盖同一窗口上还有另一个控件的情况,并且您想从该控件切换到 DataGrid。此外,您可能希望实现原始问题中描述的行为(单个制表符进入,单个制表符退出,不要通过单元格/列进行制表)。该解决方案旨在实现此目的。
注意:此解决方案假定您希望在 DataGrid 中使用 FullRow 作为您的 SelectionUnit
首先,这是应用于 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>

这种样式允许关注行,但防止关注单个单元格,这使得焦点与“FullRow”选择单元的焦点保持一致。此样式内设置的触发器是可选的 - 只有在希望在接收焦点时自动选择该行时才需要它。
在我的情况下,我希望实现单个制表符进入/离开行为,因此我还在我的DataGrid上设置了“KeyboardNavigation.TabNavigation”属性 =“Once”。
<DataGrid SelectionUnit="FullRow" KeyboardNavigation.TabNavigation="Once">

采用这种方法,我仍然可以使用上下箭头键在DataGrid接收到焦点后循环浏览行,但如果我想要快速地将焦点移动到制表顺序中的下一个控件,则可以快速地按Tab键。


这对我来说不太起作用,但很接近了!当DataGrid中有多行时,第一次切换到DataGrid会选择第一行,下一个tab键会退出DataGrid。但是,如果您选择第二行并且按tab键足够多次以循环回到DataGrid,则它会重新选择第一行。 - jep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接