Focus on DataGridCell for SelectedItem when DataGrid Receives Keyboard Focus

后端 未结 3 1232
南笙
南笙 2020-12-30 11:19

I have a DataGrid where the SelectedItem is bound to a VM Selected property. I have a search control that will do a find and the SelectedItem

相关标签:
3条回答
  • 2020-12-30 11:50

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

            var selectedRow = (DataGridRow)dataGrid1.ItemContainerGenerator.ContainerFromIndex(dataGrid1.SelectedIndex);
            FocusManager.SetIsFocusScope(selectedRow, true);
            FocusManager.SetFocusedElement(selectedRow, selectedRow);
    
    0 讨论(0)
  • 2020-12-30 11:51

    This PowerShell snippet worked for me:

    $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")))
        }
    })
    
    0 讨论(0)
  • 2020-12-30 11:52

    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:

    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);
            }));
        }
    };
    
    0 讨论(0)
提交回复
热议问题