当DataGrid获得键盘焦点时,将焦点集中在SelectedItem的DataGridCell上。

9
我有一个DataGrid,其中SelectedItem绑定到VM Selected属性。我有一个搜索控件,可以进行查找,DataGrid的SelectedItem会发生变化(并滚动到视图中)。WPF 4.0和DataGrid SelectionUnit="FullRow"。
我的问题是焦点问题。DataGrid通过附加属性/绑定接收焦点,但无法使用Up、Down、Page Up、Page Down键更改行(SelectedItem)。如果我再按Tab键,将选择显示的第一行的第一个单元格,这会更改SelectedItem。
最重要的是,当DataGrid接收焦点时,如何将键盘焦点给予SelectedItem的DataGridCell?
有许多DataGrid/Focus问题,已经尝试了一些方法。感谢您的帮助。
3个回答

11

您需要给新选择的行逻辑焦点。在选择新项目后,请尝试使用以下内容替换您的SetFocus调用:

您需要为新选择的行设置逻辑焦点。在选择新项目后,尝试使用以下代码替换您的SetFocus函数:

        var selectedRow = (DataGridRow)dataGrid1.ItemContainerGenerator.ContainerFromIndex(dataGrid1.SelectedIndex);
        FocusManager.SetIsFocusScope(selectedRow, true);
        FocusManager.SetFocusedElement(selectedRow, selectedRow);

完美运行!将此放入GotKeyboardFocus事件处理程序中,仅在e.NewFocus为DataGrid时调用。 - KornMuffin
@KornMuffin,你在使用WPF吗?我的不起作用,我只想让焦点进入我的数据网格,使箭头键起作用,但它不起作用。有什么解决办法吗? - Ahmad
@Ahmad 是的,WPF。我的DataGrid.SelectionUnit是FullRow。不确定这对你是否有影响。 - KornMuffin

1

对我来说,FocusManager解决方案无法工作。而且我需要一种更通用的方法。所以这是我想出的:

using System.Windows.Controls;

public static void RestoreFocus(this DataGrid dataGrid,
                                     int column = 0, bool scrollIntoView = false)
{
    if (dataGrid.IsKeyboardFocusWithin && dataGrid.SelectedItem != null)
    {
        // make sure everything is up to date
        dataGrid.UpdateLayout();

        if (scrollIntoView)
        {
            dataGrid.ScrollIntoView(dataGrid.SelectedItem);
        }

        var cellcontent = dataGrid.Columns[column].GetCellContent(dataGrid.SelectedItem);
        var cell = cellcontent?.Parent as DataGridCell;
        if (cell != null)
        {
            cell.Focus();
        }
    }
}

并且像这样调用它:

MyDataGrid.IsKeyboardFocusWithinChanged += (sender, e) =>
{
    if ((bool)e.NewValue == true)
    {
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Loaded, new Action(() =>
        {
            MyDataGrid.RestoreFocus(scrollIntoView: true);
        }));
    }
};

0
这个 PowerShell 片段对我起作用了:
$dataGrid = ...    
$dataGrid.add_GotKeyboardFocus({
    param($Sender,$EventArgs)
    if ($EventArgs.OldFocus -isnot [System.Windows.Controls.DataGridCell) {
        $row = $dataGrid.ItemContainerGenerator.ContainerFromIndex($dataGrid.SelectedIndex)
        $row.MoveFocus((New-Object System.Windows.Input.TraversalRequest("Next")))
    }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接