WPF DataGrid moves input focus and selection to the wrong cell when pressing tab

You’d expect that when you hit tab in the last cell the WPF data grid it would create a new row and put your focus in the first cell of that row.  It doesn’t, depending on how you have KeboardNavigation.TabNavigation set it’ll jump off somewhere you don’t expect, like the next control or back to the first item in the grid.

I was sure I was doing something wrong because it can’t behave like this, it’s just plain unusable.  But after some time I found this which suggests it’s a bug.  So, given that it didn’t look I was missing something obvious I wrote this behavior to solve the problem:

public class NewLineOnTabBehavior : Behavior<DataGrid>
{
    private bool _monitorForTab;
 
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.BeginningEdit += _EditStarting;
        AssociatedObject.CellEditEnding += _CellEnitEnding;
        AssociatedObject.PreviewKeyDown += _KeyDown;
    }
 
    private void _EditStarting(object sender, DataGridBeginningEditEventArgs e)
    {
        if (e.Column.DisplayIndex == AssociatedObject.Columns.Count - 1)
            _monitorForTab = true;
    }
 
    private void _CellEnitEnding(object sender, DataGridCellEditEndingEventArgs e)
    {
        _monitorForTab = false;
    }
 
    private void _KeyDown(object sender, KeyEventArgs e)
    {
        if (_monitorForTab && e.Key == Key.Tab)
        {
            AssociatedObject.CommitEdit(DataGridEditingUnit.Row, false);
        }
    }
 
    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.BeginningEdit -= _EditStarting;
        AssociatedObject.CellEditEnding -= _CellEnitEnding;
        AssociatedObject.PreviewKeyDown -= _KeyDown;
        _monitorForTab = false;
    }
}

 

You use it like this:

<DataGrid ItemsSource="{Binding Stuff}" CanUserAddRows="True" CanUserDeleteRows="True" 
    AutoGenerateColumns="false" KeyboardNavigation.TabNavigation="Contained">
    <i:Interaction.Behaviors>
        <Infrastructure:NewLineOnTabBehavior />
    </i:Interaction.Behaviors>
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Something}" />
        <DataGridTextColumn Binding="{Binding SomethingDifferent}" />
    </DataGrid.Columns>
</DataGrid>

 

I found that setting the KeyboardNavigation.TabNavigation to Contained behaved quite nicely.

If anyone has a better approach please let me know.  If not, I hope this saves you some time!

Advertisements

About Tom Peplow

C# .Net developer based in London and the South Coast
This entry was posted in Uncategorized and tagged . Bookmark the permalink.

5 Responses to WPF DataGrid moves input focus and selection to the wrong cell when pressing tab

  1. In what Namespace is the Behavior class that you are using?

  2. Florian Kratzer says:

    Does unfortunately not solve the problem for me. When “Tab” is pressed on the last cell (In Edit-Mode) nothing will be focused. Only the last two cells in the last two rows will be selected (but not focused). Very strange in my opinion.

    Any ideas?

    Thanks.

    Sorry for my bad english …

    • Tom Peplow says:

      I’m not sure why that wouldn’t work for you – as I said works fine in our app. But it is a filthy hack, not sure why this isn’t the default behaviour. Have you set your KeyboardNavigation.TabNavigation to contained? It’s been a while but I seem to remember there being a sweet spot between that behaviour and tab options…

      Sorry I can’t be of much more help.

      Tom

  3. Thomas Froitzheim says:

    Nice solution, thank you for sharing it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s