When DataGrid was introduced into WPF, I was happy. I really lack this control. As many other developers I found one drawback of new control. When you use DataGridTemplateColumn, it doesn’t set focus automatically on control inside DataGridTemplateColumn.CellEditingTemplate. This requires from you to click 3 times to edit the cell or press tab twice. It is very annoying. Discussion of this bug and possible solutions was made at code plex http://www.codeplex.com/Thread/View.aspx?ProjectName=wpf&ThreadId=35540 . I found my own solution. When you start to edit cell, wpf creates controls for data edit, like textboxes. So we need to transfer focus to them immediately. I created attacher class:
public class FocusAttacher
{
public static readonly DependencyProperty FocusProperty = DependencyProperty.RegisterAttached("Focus", typeof(bool), typeof(FocusAttacher), new PropertyMetadata(false, FocusChanged));
public static bool GetFocus(DependencyObject d)
{
return (bool)d.GetValue(FocusProperty);
}
public static void SetFocus(DependencyObject d, bool value)
{
d.SetValue(FocusProperty, value);
}
private static void FocusChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
((UIElement)sender).Focus();
}
}
}
Public Class FocusAttacher Public Shared ReadOnly FocusProperty As DependencyProperty = DependencyProperty.RegisterAttached(“Focus”, GetType(Boolean), GetType(FocusAttacher), New PropertyMetadata(False, New PropertyChangedCallback(AddressOf FocusChanged))) Public Shared Function GetFocus(ByVal d As DependencyObject) As Boolean Return CBool(d.GetValue(FocusProperty)) End Function Public Shared Sub SetFocus(ByVal d As DependencyObject, ByVal value As Boolean) d.SetValue(FocusProperty, value) End Sub Private Shared Sub FocusChanged(ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs) If CBool(e.NewValue) Then DirectCast(sender, UIElement).Focus() End If End Sub End Class
As you can see, this class can be attached to any UIElement and calls focus immediately.
You can use it like this:
<tk:DataGrid CanUserAddRows="True" ItemsSource="{Binding}" AutoGenerateColumns="False">
<tk:DataGrid.Columns>
<tk:DataGridTemplateColumn Header="Name">
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="3" Text="{Binding Name}" />
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Name, Mode=OneWay}" lc:FocusAttacher.Focus="True" />
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Phone">
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Phone}" Padding="3"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Phone, Mode=OneWay}" lc:FocusAttacher.Focus="True" />
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Address">
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Address}" Padding="3"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Address, Mode=OneWay}" lc:FocusAttacher.Focus="True" />
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
</tk:DataGridTemplateColumn>
</tk:DataGrid.Columns>
</tk:DataGrid>
This completely solves the problem, when you start to edit cell, focus immediately goes to required control.
Sample projects which show such datagrid and attacher class in action is available .