1
votes

I have a datagrid in which I want my Enter key to work like TAB key. So, I followed this post.

After following that post's accepted answer, I got the required functionality. But there I get a small problem.

When I press Enter on last cell of the last row of the DataGrid, a new row is added to the datagrid but the last cell of the newly added row is focused instead of first cell.

enter image description here

What I want is when I press enter on the last cell of the last row, a new row should be added and the first cell of the newly created row should be focused instead of last cell.

enter image description here

Note : Above problem occurs only when a new row is added to the datagrid. While navigating through existing rows it works as expected.

Mainly I have used 4 files in this sample project.

Person.cs

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
}

MainWindowViewModel.cs

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel()
    {
        People = new ObservableCollection<Person>();
    }

    private ObservableCollection<Person> _people;
    public ObservableCollection<Person> People
    {
        get
        {
            return _people;
        }
        set
        {
            _people = value;
            OnPropertyChanged("People");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

        <DataGrid x:Name="maindg" AutoGenerateColumns="True" 
                  ItemsSource="{Binding People}" 
                  PreviewKeyDown="DataGrid_KeyDown_1" SelectedIndex="0"   
                  GridLinesVisibility="Vertical" 
                  SelectionMode="Single" SelectionUnit="CellOrRowHeader">

        </DataGrid>

</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void DataGrid_KeyDown_1(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter) return;

        DependencyObject dep = (DependencyObject)e.OriginalSource;
        //here we just find the cell got focused ...
        //then we can use the cell key down or key up
        // iteratively traverse the visual tree
        while ((dep != null) && !(dep is DataGridCell) && !(dep is DataGridColumnHeader))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        if (dep == null)
            return;

        if (dep is DataGridCell)
        {
            //cancel if datagrid in edit mode
            maindg.CommitEdit();
            //get current cell
            DataGridCell cell = dep as DataGridCell;
            //deselect current cell
            cell.IsSelected = false;
            //find next right cell
            var nextCell = cell.PredictFocus(FocusNavigationDirection.Right);
            //if next right cell null go for find next ro first cell
            if (nextCell == null)
            {
                DependencyObject nextRowCell;
                nextRowCell = cell.PredictFocus(FocusNavigationDirection.Down);
                //if next row is null so we have no more row Return;
                if (nextRowCell == null) return;
                //we do this because we cant use FocusNavigationDirection.Next for function PredictFocus
                //so we have to find it this way
                while ((nextRowCell as DataGridCell).PredictFocus(FocusNavigationDirection.Left) != null)
                    nextRowCell = (nextRowCell as DataGridCell).PredictFocus(FocusNavigationDirection.Left);
                //set new cell as next cell
                nextCell = nextRowCell;
            }

            //change current cell
            maindg.CurrentCell = new DataGridCellInfo(nextCell as DataGridCell);
            //change selected cell
            (nextCell as DataGridCell).IsSelected = true;
            // start edit mode
            maindg.BeginEdit();
        }
        //handl the default action of keydown
        e.Handled = true;
    }
}

I have not posted the Styling code for simplicity purposes.

1
Nice pictures. Post the relevant code and XAML of what you already tried.Federico Berasategui
I have posted the code as you suggested.Vishal

1 Answers

3
votes

Replace this line of code in the DataGrid_KeyDown_1 event handler

if (nextRowCell == null) return;

With this:

if (nextRowCell == null)
{
    nextRowCell = dep;
    while ((nextRowCell as DataGridCell).PredictFocus(FocusNavigationDirection.Left) != null)
    nextRowCell = (nextRowCell as DataGridCell).PredictFocus(FocusNavigationDirection.Left);
    //change current cell
    maindg.CurrentCell = new DataGridCellInfo(nextRowCell as DataGridCell);
    //change selected cell
    (nextRowCell as DataGridCell).IsSelected = true;
    return;
}