WPF MVVM:在单击按钮时将焦点设置到 Datagrid 中的当前选定项

WPF MVVM: Set focus to current selected item in Datagrid on button click

我在 Visual Studio 2008 和 NET Framework 3.5 SP1 中有一个 MVVM WPF 应用程序。在其他控件中,此应用有一个数据网格和一个按钮。

按钮:

<Button Grid.Column="1" Command="{Binding CalculateCommand}" FocusManager.FocusedElement="{Binding ElementName=myDataGrid}" HorizontalAlignment="Right">
    <Button.Style>
        <Style TargetType="Button">
            <Setter Property="IsEnabled" Value="True" />                
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=myDataGrid, Path=SelectedItem}" Value="{x:Null}">
                    <Setter Property="IsEnabled" Value="False" />                        
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
        <Image VerticalAlignment="Center" Source="/MyWPFApp;component/Images/Calculate.png"></Image>
        <TextBlock VerticalAlignment="Center">Calculate</TextBlock>
    </StackPanel>
</Button>

我想要做的是在单击按钮后将焦点设置在数据网格中的当前选定项目上,这样当我单击键盘上的 up/down 箭头键时,我可以移动到其中的任何其他项目数据网格。

所以我尝试在按钮中设置FocusManager.FocusedElement 属性但是它不起作用。我也尝试按原样设置而不指定路径:

FocusManager.FocusedElement="{Binding ElementName=myDataGrid}"

第一次尝试,没有在属性中设置Path:

FocusManager.FocusedElement="{Binding ElementName=myDataGrid}"

当我单击键盘中向上箭头键的向下键时(单击按钮后),它会将焦点更改为 UI 中的另一个控件,该控件不是数据网格中的当前选定项。

第二次尝试,在属性中设置路径:

FocusManager.FocusedElement="{Binding ElementName=myDataGrid, Path=SelectedItem}"

它什么都不做,既不关注数据网格中的当前选定项,也不关注任何其他控件。

我也尝试过附加行为 here 但它不起作用:

<Button Grid.Column="1" Command="{Binding CalculateCommand}" classes:EventFocusAttachment.ElementToFocus="{Binding ElementName=myDataGrid}" HorizontalAlignment="Right">

再次尝试:

它在第二次按键时起作用,第一次点击被忽略。

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        if (myDataGrid.SelectedIndex > -1)
        {
            var selectedRow = (Microsoft.Windows.Controls.DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromIndex(myDataGrid.SelectedIndex);
            FocusManager.SetIsFocusScope(selectedRow, true);
            FocusManager.SetFocusedElement(selectedRow, selectedRow);
        }
   }

@Evk 解决方案完美运行。

以下应该有效:

if (myDataGrid.SelectedIndex > -1) {
    var container = (DataGridRow) myDataGrid.ItemContainerGenerator.ContainerFromIndex(myDataGrid.SelectedIndex);
    if (container != null) {
        container.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }
}

您可以将该代码放入 Button.Click 事件中(这里没有错,我们正在做的完全是仅供查看的事情)或者如果您不喜欢代码隐藏,您可以创建附加的 property\behavior 来自那个。