How to set Focus on new row after TAB Pressed in the last row in C# WPF DataGrid?

Mojtaba_Hakim 281 Reputation points
2023-01-10T10:32:07.007+00:00

I'm using C# WPF , I have a DataGrid that is bound to an ObservableCollection , I want to keep focus on DataGrid's row when user is entering value with keyboard on DataGrid, I mean when last row is focus after value entered , istead of lost focus on Datagrid lets go focus on the next row

also I want to use enter instead of TAB

but these solutions in stack overflow doesn't work for me ! : wpf-datagrid-how-to-stay-focused-on-the-bottom-of-the-datagrid-as-new-rows-are

.

What have I tried :

1- First case:

if (YOUR_DATA_GRID.Items.Count > 0 && YOUR_DATA_GRID != null)
{
     //___________This piece of code is to go to the next line with enter for a single line that is entered for the first time and not to focus on the new line.
         bool ISOK = true;
         //If there is no more than one line
         // The reason for minus 2 is that because we gave something to it in Add New Item, a new line is added, so if we see 1 line
         //It means that the number of items is 2, item zero, the first line, item 1, a new line named New Place Holder
        if (YOUR_DATA_GRID.Items.Count - 2 <= 2)
        {
           //Don't get null error from where you delete the line and then refresh
            if (!(YOUR_DATA_GRID.Items[0] as CUSTOM_MODEL is null))
            {
               // if is new
                if ((YOUR_DATA_GRID.Items[0] as CUSTOM_MODEL).id is null)
                {
                    ISOK = false;
                    return;
                }
            }
        }
       //If the above condition is not met and there is also the last line, let's put the focus on the new line
        if (ISOK)
        {
            if ((YOUR_DATA_GRID.Items.Count - 2) == CURRENT_ROW_INDEX)
            {
                e.Row.Loaded += Row_Loaded;
            }
        }
    }     
    void Row_Loaded(object sender, RoutedEventArgs e)
    {
        YOUR_DATA_GRID.SelectedItem = YOUR_DATA_GRID.Items[YOUR_DATA_GRID.Items.Count - 1];
        YOUR_DATA_GRID.ScrollIntoView(YOUR_DATA_GRID.Items[YOUR_DATA_GRID.Items.Count - 1]);
        DataGridRow dgrow = (DataGridRow)YOUR_DATA_GRID.ItemContainerGenerator.ContainerFromItem(YOUR_DATA_GRID.Items[YOUR_DATA_GRID.Items.Count - 1]);
        dgrow.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }

.

2- Second case:

Using below method in these events :

RowEditEnding

AddingNewItem

interestingly this code doesn't work to focus on the next row !:

 var IIDEX = CURRENT_ROW_INDEX + 1;

        if (IIDEX > YOUR_DATA_GRID.Items.Count - 1)
        {
            IIDEX = 0;
        }
        DataGridRow row = (DataGridRow)YOUR_DATA_GRID.ItemContainerGenerator.ContainerFromIndex(IIDEX);
        if (row is null)
        {
            YOUR_DATA_GRID.ScrollIntoView(YOUR_DATA_GRID.Items[IIDEX]);
            row = (DataGridRow)YOUR_DATA_GRID.ItemContainerGenerator.ContainerFromIndex(IIDEX);
            object item = YOUR_DATA_GRID.Items[IIDEX];
            YOUR_DATA_GRID.SelectedItem = item;
            row.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

        }
        else
        {
            object item = YOUR_DATA_GRID.Items[IIDEX];
            YOUR_DATA_GRID.SelectedItem = item;
            YOUR_DATA_GRID.ScrollIntoView(item);
            row.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }

all of thing's that I've tried, didn't work

My Full Source code + Database SQL Server: w5ZyzbzZ

NOTE:↑ in that source code I removed my tries for Focus On next row ,

please guide me how do I do that

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,681 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,306 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
767 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Hui Liu-MSFT 40,786 Reputation points Microsoft Vendor
    2023-01-11T06:01:11.0733333+00:00

    I tested it with the code below. You could see if it helps you.

    I also tested your code and it seems to work fine. Can you point out where the specific problem is?

    According to official documentation Default keyboard and mouse behavior in DataGrid control.

    ENTER Commits any changes to the current cell and row, and moves focus to the cell directly below the current cell. If focus is on the last row, commit any changes without moving focus.

    MainWindow.xaml:

    
    <Window.DataContext>
    
            <local:ViewModel />
    
        </Window.DataContext>
    
        <Grid>
    
            <DataGrid x:Name="dg"  ItemsSource="{Binding Users}" SelectedItem="{Binding SelecedItme }" AutoGenerateColumns="False" CanUserAddRows="True"  >
    
                <DataGrid.Columns>
    
                    <DataGridTextColumn x:Name="Id" Binding="{Binding Id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Id" />
    
                    <DataGridTextColumn x:Name="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Name" />
    
                    
    
                </DataGrid.Columns>
    
            </DataGrid>
    
        </Grid>
    
    
    
    using System.Windows;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    
    using System.Runtime.CompilerServices;
    
    namespace DataGridNextRowCell
    {
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
        }
        public class ViewModel : INotifyPropertyChanged
        {
            private User selecedItme;
            public User SelecedItme
            {
                get { return selecedItme; }
                set
                {
                    if (selecedItme != value)
                    {
                        selecedItme = value;
                        OnPropertyChanged("SelecedItme");
                    }
                }
            }
            private ObservableCollection<User> users = new ObservableCollection<User>();
            public ObservableCollection<User> Users
            {
                get { return users; }
                set
                {
                    if (users != value)
                    {
                        users = value;
                        OnPropertyChanged("Users");
                    }
                }
            }
            public ViewModel()
            {
                Users.Add(new User() { Id = 1, Name = "user1" });
                Users.Add(new User() { Id = 2, Name = "user2" });
                Users.Add(new User() { Id = 3, Name = "user3" });
                Users.Add(new User() { Id = 5, Name = "user4" });
                Users.Add(new User() { Id = 6, Name = "user5" });
            }
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged([CallerMemberName] string name = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
        }
        public class User
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    }
    
    

    The result of my test (press Enter):

    6

    The results of testing your code (press Enter):

    7


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our [documentation][5] to enable e-mail notifications if you want to receive the related email notification for this thread.