在WPF数据网格中导航

时间:2014-07-04 20:33:32

标签: c# wpf datagrid focus

我有一个数据网格,我想让 Enter 键像 TAB 键一样工作。所以,我跟着this发帖。

按照该帖子接受的答案后,我获得了所需的功能。但是我遇到了一个小问题。

当我在DataGrid的最后一行的最后一个单元格上按 Enter 时,会向数据网格添加一个新行,但是新添加的行的最后一个单元格将被聚焦而不是第一个单元格。 / p>

enter image description here

我想要的是当我在最后一行的最后一个单元格上按Enter键时,应该添加一个新行,并且应该聚焦新创建的行的第一个单元格而不是最后一个单元格。

enter image description here

注意:只有在向数据网格添加新行时才会出现上述问题。在浏览现有行时,它按预期工作。

主要是我在这个示例项目中使用了4个文件。

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;
    }
}

为了简单起见,我没有发布样式代码。

1 个答案:

答案 0 :(得分:3)

替换DataGrid_KeyDown_1事件处理程序中的这行代码

if (nextRowCell == null) return;

有了这个:

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;
}