WPF DataGrid如何通过单击(或触摸)选择DataGridCell内部的控件

3bygqnnd  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(171)

我有一个DataGrid,它有一个DataGridTemplateColumn,它为CellTemplate定义了一个TextBlock(用于值显示),为CellEditingTemplate定义了一个TextBox(用于值编辑)。我想单击DataGrid的一个单元格,光标应该在该单元格的TextBox内,这样我就不必多次单击,直到TextBox具有输入焦点。
这是我的DataGrid:

<DataGrid ItemsSource="{Binding Path=Entries}" >
    <DataGrid.Columns>
        <DataGridTextColumn Header="SomeData" Binding="{Binding Path=SomeData}" Width="Auto" />
        
        <DataGridTemplateColumn Header="Comment" Width="Auto">
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBox Name="InputTextBox" Text="{st:WpfBinding Path=Comment}"  />
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding Path=Comment}" PreviewMouseDown="UIElement_OnPreviewMouseDown" />
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

我尝试使用单元格TextBlock的PreviewMouseDown事件,但我不确定这是否可以访问TextBox来聚焦它或其他东西。
我的事件处理程序看起来像这样:

private void UIElement_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var targetCell = this.GetDataGridCell(sender, e);

    if (targetCell != null)
    {
        targetCell.IsEditing = true;

        if (targetCell.IsEditing)
        {
            // Do something ?
        }
    }
}

private DataGridCell GetDataGridCell(object sender, MouseEventArgs e)
{
    var hit = VisualTreeHelper.HitTest((Visual)sender, e.GetPosition((IInputElement)sender));
    DependencyObject cell = VisualTreeHelper.GetParent(hit.VisualHit);

    while (cell != null && !(cell is DataGridCell))
    {
        cell = VisualTreeHelper.GetParent(cell);
    }

    DataGridCell targetCell = cell as DataGridCell;

    return targetCell;
}

这已经允许我设置单击的DataGridCell的IsEditing属性。但我仍然需要第二次点击来设置TextBox的焦点。有什么建议吗?这是正确的做法吗?

qybjjes1

qybjjes11#

我在另一篇文章中找到了解决方案:wpf datagrid single click edit with DataGridTemplateColumn not working
您必须订阅TextBox的Loaded事件,然后为其设置焦点。
WPF:

<DataGrid ItemsSource="{Binding Path=Entries}" >
    <DataGrid.Columns>
        <DataGridTextColumn Header="SomeData" Binding="{Binding Path=SomeData}" Width="Auto" />
        
        <DataGridTemplateColumn Header="Comment" Width="Auto">
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBox Name="InputTextBox" Text="{Binding Path=Comment}" Loaded="InputTextBox_Loaded" />
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding Path=Comment}" PreviewMouseDown="UIElement_OnPreviewMouseDown" />
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

代码隐藏:

private void UIElement_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var targetCell = this.GetDataGridCell(sender, e);

    if (targetCell != null)
    {
        targetCell.IsEditing = true;
    }
}

private DataGridCell GetDataGridCell(object sender, MouseEventArgs e)
{
    var hit = VisualTreeHelper.HitTest((Visual)sender, e.GetPosition((IInputElement)sender));
    DependencyObject cell = VisualTreeHelper.GetParent(hit.VisualHit);

    while (cell != null && !(cell is DataGridCell))
    {
        cell = VisualTreeHelper.GetParent(cell);
    }

    DataGridCell targetCell = cell as DataGridCell;

    return targetCell;
}

private void InputTextBox_Loaded(object sender, RoutedEventArgs e)
{
    var control = (TextBox)sender;
    control.Focus();
}

相关问题