WPF DataGrid.selectedIndex没有完全关注

时间:2013-03-03 20:21:51

标签: c# wpf xaml focus observablecollection

我想在数据网格中选择automaticaaly我的第一个项目(加载我的表单时)

这是我的代码

myDataGridEvtCode.Focus();
myDataGridEvtCode.SelectedIndex = 0;

我的问题是,如果我使用箭头(向下),行不会改变,我需要输入3次才能更改所选行。我认为这是因为我的SelectedItem非常集中。

非常感谢:)

2 个答案:

答案 0 :(得分:1)

我从各种资源中收集了DataGrid行键盘的信息,最后我的解决方案如下:

public void SelectRow(DataGrid grid, int rowIndex)
    {
        grid.SelectedItem = null;

        object item = grid.Items[rowIndex];

        grid.SelectedItem = item;

        var row = grid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
        if (row == null)
        {
            grid.ScrollIntoView(item);
            row = grid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
        }

        if (row != null)
        {
            row.Focus();
            FocusManager.SetIsFocusScope(row, true);
            FocusManager.SetFocusedElement(row, row);
        }
    }

此外,当我们尝试使用箭头键将焦点从所选项目行移动到下一行时,会出现一个带有DataGrid键盘行为的小错误。 它会在第一次按键时将焦点移动到行容器中的当前行(这很奇怪,因为焦点在某种程度上不在SelectRow方法中选择的选定行项目上。)

我找到了一个解决方案,并根据我的目的对其进行了修改。

Here is一个解释,如何修复此错误。

基于此,这是我的意识:

private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
    {
        if (grid.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
        {
            int index = grid.SelectedIndex;

            if (index >= 0)
            {
                var row = grid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;

                if (row != null)
                {
                    row.Focus();

                    var presenter = FindVisualChild<DataGridCellsPresenter>(row);
                    var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(0);
                    cell.Focus();

                    FocusManager.SetIsFocusScope(row, true);
                    FocusManager.SetFocusedElement(cell, cell);
                }

            }
        }
    }

public static TChildItem FindVisualChild<TChildItem>(DependencyObject obj) where TChildItem : DependencyObject
    {
        for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = System.Windows.Media.VisualTreeHelper.GetChild(obj, i);
            if (child is TChildItem)
                return (TChildItem)child;

            var childOfChild = FindVisualChild<TChildItem>(child);
            if (childOfChild != null)
                return childOfChild;
        }
        return null;
    }

并订阅构造函数中的事件:

grid.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;

我希望它可以帮助别人找出这个问题。

答案 1 :(得分:0)

WPF中有多种类型的焦点,包括逻辑焦点和键盘焦点。听起来像所选行正在接收逻辑焦点而不是键盘焦点。您可以使用以下设置键盘焦点:

Keyboard.Focus(elementToFocus);

然而根据我的经验,焦点会变得相当复杂。它通常需要涉及FocusManager,特别是在非平凡的场景中。

我建议使用reading up on WPF Focus并摆弄KeyboardFocusManager个对象,直到您按照自己的方式行事。