3

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.

Willy
  • 9,848
  • 22
  • 141
  • 284
  • 1
    If I were you - I'd just set focus to grid in `Button.Click` event, because that's completely view thing, not related to view models. If you hate code-behind for some reason - you can do the same with attached properties \ behaviors. – Evk Oct 24 '17 at 10:41
  • @Evk See my last line in the post, I have just update. I have tried and attached behaviour and it is not working. – Willy Oct 24 '17 at 10:45
  • So that means even simple Button.Click handler with `myDataGrid.Focus()` inside does not working either? – Evk Oct 24 '17 at 10:46
  • @Evk using a simple Button.Click event and setting myDataGrid.Focus() within Button.Click event in code-behind does not work. When I press up/down arrow key it does not move to next item in the datagrid, instead next control is getting the focus depending on if I click up or down arroy key. – Willy Oct 24 '17 at 10:50

1 Answers1

3

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.

Evk
  • 98,527
  • 8
  • 141
  • 191