Reputation: 132
I have a DataGrid with a DataGridTemplateColumn that defines a TextBlock for the CellTemplate (for value displaying) and a TextBox for the CellEditingTemplate (for value editing). I want to click on a cell of the DataGrid and the cursor should be inside the TextBox of that cell so that I don't have to click multiple times until the TextBox has the input focus.
This is my 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>
I tried to use the PreviewMouseDown event of the cell's TextBlock, but I'm not sure if this works to get access to the TextBox for focussing it or something.
My event handler looks like this:
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;
}
This already allows me to set the IsEditing property of the clicked DataGridCell. But still I need a second click to set the focus for the TextBox. Any suggestions? Is this even the correct approach?
Upvotes: 0
Views: 54
Reputation: 132
I found the solution in another post: wpf datagrid single click edit with DataGridTemplateColumn not working
You have to subscribe to the Loaded event of the TextBox and then set the focus for it.
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>
Code behind:
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();
}
Upvotes: 0