0

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

这是我的代码

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

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

非常感谢 :)

4

2 回答 2

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 方法中选择的选定行项上)。

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

这是一个解释,如何修复这个错误。

基于它,这是我的实现:

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;

我希望它能帮助某人解决这个问题。

于 2015-12-22T09:32:39.797 回答
0

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

Keyboard.Focus(elementToFocus);

然而,根据我的经验,Focus 可能会变得非常复杂。它通常需要涉及FocusManager,尤其是在非平凡的场景中。

我建议阅读 WPF Focus并摆弄KeyboardandFocusManager对象,直到你让它以你​​想要的方式运行。

于 2013-03-03T21:39:37.893 回答