WPF DataGridTemplateColumn。我错过什么了吗?
您的问题源于这样一个事实,即每个单元格都将其编辑器放在一个内容控件中,该控件首先接收焦点,然后您必须再次对编辑器进行制表。如果查看GenerateEditingElement方法中DataGridTemplateColumn的代码,它将调用LoadTemplateContent方法,该方法执行以下操作:WPF DataGridTemplateColumn。我错过什么了吗?,wpf,datagrid,focus,wpfdatagrid,wpftoolkit,Wpf,Datagrid,Focus,Wpfdatagrid,Wpftoolkit,您的问题源于这样一个事实,即每个单元格都将其编辑器放在一个内容控件中,该控件首先接收焦点,然后您必须再次对编辑器进行制表。如果查看GenerateEditingElement方法中DataGridTemplateColumn的代码,它将调用LoadTemplateContent方法,该方法执行以下操作: if (Grid.CurrentColumn.Header.ToString() == "UserName") { if (e.Key != Key.E
if (Grid.CurrentColumn.Header.ToString() == "UserName")
{
if (e.Key != Key.Escape)
{
Grid.BeginEdit();
// Simply send another TAB press
if (Keyboard.FocusedElement is Microsoft.Windows.Controls.DataGridCell)
{
var keyEvt = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Tab) { RoutedEvent = Keyboard.KeyDownEvent };
InputManager.Current.ProcessInput(keyEvt);
}
}
}
查看它如何创建新的内容演示者以将模板放入其中。其他人以各种方式处理了这个问题,我派生了自己的专栏类型来处理这个问题。(因此我不会创建额外的元素或将内容演示者设置为不接收焦点)在这种情况下,他们使用焦点管理器处理相同的问题(我没有测试此代码)
如果您有一个用户控件作为编辑器,那么您可以将该模式与焦点管理器一起使用,或者对已加载的事件使用事件处理程序。我的方法是使用TriggerAction,在加载时将焦点设置为所需的模板元素 触发器非常简单:
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<Grid FocusManager.FocusedElement="{Binding ElementName=txt1}">
<TextBox Name="txt1" Text="{Binding XPath=@ISBN}"
BorderThickness="0" GotFocus="TextBox_GotFocus"/>
</Grid>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
public类takefocus并选择textonvisiblebehavior:TriggerAction
{
受保护的覆盖无效调用(对象参数)
{
调度程序。开始启动(
DispatcherPriority.已加载,
新操作(()=>
{
AssociatedObject.Focus();
AssociatedObject.SelectAll();
}));
}
}
DataTemplate如下所示:
public class TakeFocusAndSelectTextOnVisibleBehavior : TriggerAction<TextBox>
{
protected override void Invoke(object parameter)
{
Dispatcher.BeginInvoke(
DispatcherPriority.Loaded,
new Action(() =>
{
AssociatedObject.Focus();
AssociatedObject.SelectAll();
}));
}
}
您可以为其他元素类型编写其他触发器。您面临的问题是DataGridTemplateColumn中的控件(例如TextBox)包含在DataGridCell中。默认情况下,DataGridCell具有制表位停止功能。因此,必须按TAB键两次才能将焦点转到TextBox控件的原因是。解决方案是禁用DataGridCell的制表位功能。这可以通过DataGridCell的样式完成 以下是解决方案:
<DataTemplate>
<TextBox Text="{Binding Path=Price, Mode=TwoWay}"
MinHeight="0"
Padding="1,0"
Height="20">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Loaded">
<Behaviors:TakeFocusAndSelectTextOnVisibleBehavior />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</TextBox>
</DataTemplate>
以下是我的方法。这与@Nalin Jayasuriya的答案非常接近,但我不想创造一种风格。此外,此解决方案还会选择文本框中的文本。无论如何,hole DataGrid的XAML如下所示
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
</Style>
有关更多信息,请查看我的博客:
这是一种享受,但这确实是一种丑陋的黑客行为…:(我希望MS能找到一种提供这种功能的好方法FocusManager方法工作得很好。为了获得选定的内容,您还可以添加一个获得焦点的方法:private void StrikeTextBox_GotFocus(object sender,routedEventTargets e){var textBox=(textBox)sender;Dispatcher.BeginInvoke(new Action(textBox.SelectAll));}我认为此功能需要来自Expression Blend的dll
<DataTemplate>
<TextBox Text="{Binding Path=Price, Mode=TwoWay}"
MinHeight="0"
Padding="1,0"
Height="20">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Loaded">
<Behaviors:TakeFocusAndSelectTextOnVisibleBehavior />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</TextBox>
</DataTemplate>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
</Style>
<DataGrid Name="TextBlockDataGrid" ItemsSource="{Binding Path=Rows}" Style="{StaticResource DefaultSettingsDataGrid}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Text}" IsReadOnly="True"/>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderThickness="{Binding ErrorBorderThickness}" BorderBrush="{Binding ErrorBorderBrush}">
<TextBox Text="{Binding UserText, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
HorizontalAlignment="Right"
GotKeyboardFocus="TextBox_GotKeyboardFocus"
PreviewMouseDown="TextBox_PreviewMouseDown"
Style="{StaticResource DefaultTextBox}"/>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
try
{
((TextBox)sender).SelectAll();
}
catch (Exception ex) { GlobalDebug.debugForm.WriteText(ex); }
}
private void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
try
{
// If its a triple click, select all text for the user.
if (e.ClickCount == 3)
{
((TextBox)sender).SelectAll();
return;
}
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
{
parent = System.Windows.Media.VisualTreeHelper.GetParent(parent);
}
if (parent != null)
{
if (parent is TextBox)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focussed, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
}
}
}
catch (Exception ex) { GlobalDebug.debugForm.WriteText(ex); }
}