如何在单元格获得焦点时立即进入编辑模式

5
假设我有一个数据网格。假设所有列都是模板列。当任何单元格获得焦点时,我希望它进入编辑模式。 我到目前为止尝试过的: 我已经创建了一个DataGridCell样式,如下所示:
<Style TargetType="{x:Type DataGridCell}">
    <EventSetter Event="GotFocus" Handler="DataGridCell_GotFocus" />
</Style>

在窗口的代码后台中:
private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
    {
        cell.IsEditing = true;
    }
}

以上尝试存在的问题:

我必须单击单元格才能将其置于编辑模式。


1
那么,你的需求是什么?只需单击单元格即可聚焦并进入编辑模式,这对我来说似乎非常完美。不是吗? - Rohit Vats
不,当我在单元格上按TAB键时,其他单元格会获得焦点,但不会进入编辑模式。我的意思是,我希望单元格在获得焦点时立即进入编辑模式。 - Vishal
根据当前的行为,我必须按两次TAB键才能进入单元格编辑模式。 - Vishal
你是否为TemplateColumn定义了CellEditingTemplate并在其中放置了TextBox? - Rohit Vats
@RohitVats 是的,我已经按照您的要求完全完成了。 - Vishal
2个回答

6
当焦点在单元格上时,它会进入编辑模式,但是文本框没有键盘焦点,所以下一个选项卡按键将被文本框吃掉并获得焦点。
正如你所提到的,你必须按两次Tab才能将焦点移动到下一个单元格。你可以在加载事件中将焦点放在文本框上。
用于虚拟元素的XAML:
<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Name}" Loaded="TextBox_Loaded"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

后台代码:

private void TextBox_Loaded(object sender, RoutedEventArgs e)
{
    (sender as TextBox).Focus();
}

当然,您可以将处理程序移动到数据网格中所有TextBox的基本样式中,这样您就不必为所有单元格挂钩处理程序。

如果您不想使用处理程序,也可以使用定义的交互触发器来实现,例如在这里中定义的:

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Name}">
            <Interactivity:Interaction.Triggers>
                <Interactivity:EventTrigger EventName="Loaded">
                    <local:TakeFocusAction />
                </Interactivity:EventTrigger>
            </Interactivity:Interaction.Triggers>
        </TextBox>
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

行为触发动作:

public class TakeFocusAction : TriggerAction<UIElement>
{
    protected override void Invoke(object parameter)
    {
        AssociatedObject.Focus();
    }
}

1

这里有一个使其可编辑的技巧

BeginEdit() 方法将当前单元格置于编辑模式。

示例

    private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
        {
            var parent = VisualTreeHelper.GetParent(cell);
            while (parent != null && parent.GetType() != typeof(DataGrid))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }
            DataGrid dGrid = parent as DataGrid;
            dGrid.BeginEdit();
        }
    }

如果您可以访问数据网格,则可能不需要查找它。
例如。
    private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
        {
            dGrid.BeginEdit();
        }
    }

更新:FocusManager 技巧

如果焦点是唯一的问题,您可以利用 FocusManager 通过设置 FocusManager.FocusedElement。试试吧,它可以不需要后台代码就能工作。

示例

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Name}" 
                     FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

请注意,我已经通过绑定到 self 将 FocusedElement 设置为 TextBox,这样可以在加载后将 TextBox 置于焦点(因为它进入编辑模式)。

我可以访问数据网格,但结果是相同的。 - Vishal
事件处理程序被调用了吗?dGrid.BeginEdit() 被执行了吗? - pushpraj

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