按 Enter 时,WPF DataGrid 似乎忽略了 IsTabStop 设置
WPF DataGrid seems to ignore IsTabStop setting, when pressing Enter
我有一个包含很多列的数据网格。现在通常用户可以按 TAB 键在 DataGrid 单元格中的控件之间循环。数据网格单元格已设置为 IsTabStop = false,因此它跳过了对单元格本身的关注,它只是落空,直到焦点被赋予实际控件。
如果用户按 Enter 键,这似乎不起作用,因为他们想在同一列中工作。 DataGrid 会将焦点传递给 COLUMN 中的下一个单元格,但它也会忽略 IsTabStop 设置,因此它只会将焦点赋予单元格本身,而不是内部控件。
关于如何解决这个问题的任何想法。
简短示例
<DataGrid AutoGenerateColumns="False" Name="grid1" >
<DataGrid.Resources>
<Style TargetType="{x:Type Border}" x:Key="coloredBorder">
<Setter Property="Background" Value="Yellow"/>
</Style>
<Style TargetType="DataGridCell">
<Setter Property="IsTabStop" Value="False"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding A, Mode=OneWay}" Header="A"/>
<DataGridTemplateColumn Header="B">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" BorderThickness="0,0,1,0" Width="20" Height="20" Style="{DynamicResource coloredBorder}"/>
<ComboBox Grid.Column="1" SelectedItem="{Binding A, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding MenuItems, ElementName=window}"></ComboBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
我还为此添加了示例 WPF 应用程序 here。要重现,请单击其中一个组合框以使其成为焦点。按下 tab 键,您将看到下一个组合框正常获得焦点。如果我添加了多个组合框列,右侧的组合框将获得焦点。
但是,如果您按 Enter,焦点将转到下面的单元格,但它不会跳过该单元格并转到单元格内容。相反,单元格被突出显示。
像这样:
我通过附上 属性:
解决了这个问题
using System.Windows;
using System.Windows.Input;
namespace GridTabbing
{
public class EnterKeySample
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var ue = e.OriginalSource as FrameworkElement;
if (e.Key == Key.Enter)
{
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
}
}
private static void ue_Unloaded(object sender, RoutedEventArgs e)
{
var ue = sender as FrameworkElement;
if (ue == null) return;
ue.Unloaded -= ue_Unloaded;
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
typeof(EnterKeySample), new UIPropertyMetadata(false, IsEnabledChanged));
static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ue = d as FrameworkElement;
if (ue == null) return;
if ((bool)e.NewValue)
{
ue.Unloaded += ue_Unloaded;
ue.PreviewKeyDown += ue_PreviewKeyDown;
}
else
{
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
}
}
}
奇怪的是,它所做的唯一一件事就是告诉 WPF 在用户按下 Enter 时将焦点向下传递,我本以为这已经发生了,但显然不是。
我有一个包含很多列的数据网格。现在通常用户可以按 TAB 键在 DataGrid 单元格中的控件之间循环。数据网格单元格已设置为 IsTabStop = false,因此它跳过了对单元格本身的关注,它只是落空,直到焦点被赋予实际控件。
如果用户按 Enter 键,这似乎不起作用,因为他们想在同一列中工作。 DataGrid 会将焦点传递给 COLUMN 中的下一个单元格,但它也会忽略 IsTabStop 设置,因此它只会将焦点赋予单元格本身,而不是内部控件。
关于如何解决这个问题的任何想法。
简短示例
<DataGrid AutoGenerateColumns="False" Name="grid1" >
<DataGrid.Resources>
<Style TargetType="{x:Type Border}" x:Key="coloredBorder">
<Setter Property="Background" Value="Yellow"/>
</Style>
<Style TargetType="DataGridCell">
<Setter Property="IsTabStop" Value="False"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding A, Mode=OneWay}" Header="A"/>
<DataGridTemplateColumn Header="B">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" BorderThickness="0,0,1,0" Width="20" Height="20" Style="{DynamicResource coloredBorder}"/>
<ComboBox Grid.Column="1" SelectedItem="{Binding A, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding MenuItems, ElementName=window}"></ComboBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
我还为此添加了示例 WPF 应用程序 here。要重现,请单击其中一个组合框以使其成为焦点。按下 tab 键,您将看到下一个组合框正常获得焦点。如果我添加了多个组合框列,右侧的组合框将获得焦点。
但是,如果您按 Enter,焦点将转到下面的单元格,但它不会跳过该单元格并转到单元格内容。相反,单元格被突出显示。 像这样:
我通过附上 属性:
解决了这个问题using System.Windows;
using System.Windows.Input;
namespace GridTabbing
{
public class EnterKeySample
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}
static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var ue = e.OriginalSource as FrameworkElement;
if (e.Key == Key.Enter)
{
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
}
}
private static void ue_Unloaded(object sender, RoutedEventArgs e)
{
var ue = sender as FrameworkElement;
if (ue == null) return;
ue.Unloaded -= ue_Unloaded;
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
typeof(EnterKeySample), new UIPropertyMetadata(false, IsEnabledChanged));
static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ue = d as FrameworkElement;
if (ue == null) return;
if ((bool)e.NewValue)
{
ue.Unloaded += ue_Unloaded;
ue.PreviewKeyDown += ue_PreviewKeyDown;
}
else
{
ue.PreviewKeyDown -= ue_PreviewKeyDown;
}
}
}
}
奇怪的是,它所做的唯一一件事就是告诉 WPF 在用户按下 Enter 时将焦点向下传递,我本以为这已经发生了,但显然不是。