wpf 当 DataGrid 接收键盘焦点时,将焦点放在 SelectedItem 的 DataGridCell 上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17117281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:00:48  来源:igfitidea点击:

Focus on DataGridCell for SelectedItem when DataGrid Receives Keyboard Focus

wpfmvvmfocuswpfdatagrid

提问by KornMuffin

I have a DataGridwhere the SelectedItemis bound to a VM Selected property. I have a search control that will do a find and the SelectedItemof the DataGridchanges (and scrolls into view). WPF 4.0 and DataGridSelectionUnit="FullRow".

我有一个DataGridSelectedItem绑定到一个VM Selected属性。我有一个搜索控制,将做一个查找和SelectedItemDataGrid变化(和滚动到视图)。WPF 4.0 和DataGridSelectionUnit="FullRow".

My problem is with the focus. The DataGridreceives focus (via attached property / binding) but you can't use the Up, Down, Page Up, Page Downkeys to change rows (SelectedItem). If I tab again, the first cell of the first row displayed is selected which changes the SelectedItem.

我的问题是焦点。的DataGrid(/经由附加属性结合)接收焦点但不能使用UpDownPage UpPage Down键改变行(SelectedItem)。如果我再次使用 Tab 键,则会选择显示的第一行的第一个单元格,这会更改SelectedItem.

Bottom line, how can I give keyboard focus to the DataGridCellfor the SelectedItemwhen the DataGridreceives focus?

最重要的DataGridCell是,SelectedItemDataGrid接收到焦点时,如何将键盘焦点放在 ?

There are so many DataGrid/ Focusquestions and tried a few things already. Thanks for your help.

有很多DataGrid/Focus问题,并且已经尝试了一些事情。谢谢你的帮助。

采纳答案by Richard E

You need to give the newly selected row logical focus. After selecting the new item try replacing your SetFocuscall with this:

您需要为新选择的行赋予逻辑焦点。选择新项目后,请尝试用以下内容替换您的SetFocus电话:

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

回答by W1M0R

This PowerShell snippet worked for me:

这个 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")))
    }
})

回答by Tim Pohlmann

The FocusManager solution didn't work for me for some reason. Also I required a more general apporach. So here is, what I came up with:

由于某种原因,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();
        }
    }
}

And call it like this:

并这样称呼它:

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