简体   繁体   中英

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

I have a MVVM WPF app in Visual Studio 2008 and NET Framework 3.5 SP1. Among other controls, this app have a datagrid and a button.

Button :

<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>

What I am trying to do is to set focus on the current selected item in the datagrid once button is clicked so when I click on up/down arrow key in the keyboard I can move to any other item in the datagrid.

So I have tried to set FocusManager.FocusedElement property in the button but it is not working. I have also tried to set as is without specifying the Path:

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

In the first attempt, without setting the Path in the property:

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

when I click on down of up arrow key in the keyboard (after clicking button), it change the focus to another control in the UI that is not the current selected item in the datagrid.

In the second attempt, setting the Path in the property:

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

it simply does nothing, neither no focus in the current selected item in the datagrid nor in any other control.

Also I have tried an attached behaviour as said here but it is not working:

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

Another attempt :

It works on second key click, first click is ignored.

    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 Solution works perfectly.

The following should work:

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

You can put that code into Button.Click event (nothing wrong here, what we are doing is completely view-only thing) or if you don't like code-behind you can create attached property\\behavior from that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM