Set keyboard focus when the user begins editing a wpf datagrid templatecolumn ?

The problem:
When I begin editing a grid cell, I'd expect the keyboard focus to be set the edit control for the cell. In case of a textbox, I'd also like the existing contents to be selected by default ; so that i can begin typing and set a new value quickly.


This works for the default data grid column types... except for a DataGridTemplateColumn ; a column whose display & edit behavior can be customized. You can use a templateselector to dynamically choose the templates to be used for displaying and editing values.

However if you attempt to tab into a TemplateColumn cell and hit F2 to begin editing, you'd find that you can't start typing in it. You need to click in it once or press Tab once more to do that. Compare the behavior of a TextColumn and TemplateColumn showing the same bound value as shown in the code below. The TextColumn behaves as expected. The edit control receives keyboard focus and all the text in it is selected.

Highly unintuitive.


The fix for the keyboard focus thing turned out to be setting FocusManager.FocusedElement attached property on the desired control in your Data Template for editing. Check out the sample below with/without the FocusedElement property setter :



...
<DataTemplate x:Key="DefaultTitleTemplate">
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
<DataTemplate x:Key="EditTitleTemplate">

<TextBox x:Name="Fox"

FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"
Text="{Binding Path=Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource HighlightTextBoxStyle}"
>
</TextBox>
</DataTemplate>
</Grid.Resources>
<DockPanel>
<TextBox DockPanel.Dock="Top" x:Name="Test" Text="{Binding Path=(FocusManager.FocusedElement).Name, ElementName=MyWindow}"
Style="{StaticResource HighlightTextBoxStyle}"/>
<toolkit:DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
<toolkit:DataGrid.Columns>
<toolkit:DataGridTemplateColumn Header="Templated Title"
CellTemplate="{StaticResource DefaultTitleTemplate}"
CellEditingTemplate="{StaticResource EditTitleTemplate}">

</toolkit:DataGridTemplateColumn>
<toolkit:DataGridTextColumn Header="Title" >
<toolkit:DataGridTextColumn.Binding>
<Binding Path="Title">
<Binding.ValidationRules>
<local:CannotBeginWithX/>
</Binding.ValidationRules>
</Binding>
</toolkit:DataGridTextColumn.Binding>
</toolkit:DataGridTextColumn>
...



Still struggling to find the
fix to auto-select the text in the textbox in the expanded edit cell template.

Update: Got this to work by subscribing to the PreparingCellForEdit event. The editor is passed in as an event argument. For a templatedcolumn, the grid is unable to guess your editor control type. So you need to cast it to your particular editor type and call Focus()+SelectAll() on it. I subscribed to the event in the ctor and wasn't able to get the editor.. You need to wait till the Loaded event to subscribe. Then it worked.

2 comments:

  1. This works when you have only one templatecolumn. with multiple templatecolumns it doesn't work.

    ReplyDelete
  2. Worked like a charm. Thanks a lot!

    ReplyDelete