-1

I am trying to make a small modal window with a search box and a list of results. My goal is for the focus to land in the first element of the List after searching.

Problem

Unfortunately, I stuck in a situation where my focus lands on the window itself after searching.

My TextBox has an InputBinding that triggers on enter to perform the search:

<TextBox Grid.Column="1" Grid.Row="1" 
         Text="{Binding Supplier.LeverandorNavn, UpdateSourceTrigger=PropertyChanged}" 
         x:Name="txtBoxSupplierName" Width="150" 
         HorizontalAlignment="Left" VerticalAlignment="Top" 
         TabIndex="1">
        <TextBox.InputBindings>
            <KeyBinding Key="Return" Command="{Binding SearchCommand}" />
        </TextBox.InputBindings>
</TextBox>

I have been trying to use Snoop to understand the flow of events. As seen here, the KeyDown is handled by my txtBoxSupplerName Textbox fine. But I cannot understand why the levWindow gets focus after my command executes. enter image description here

I have attempted to manually set the focus element, but it has no effect.

Questions

Can someone explain to me, why the focus lands on the window by default?

Can someone suggest an approach, on how I can take control of the focus myself and avoid this default behavior?

  • I am challenged by the fact that the DataGrid needs some time to redraw itself before the row I want to focus is visible.

Properties

public ClientLeverandor ValgtLeverandør
{
    get { return _valgtLeverandør; }
    set { SetProperty(ref _valgtLeverandør, value, nameof(ValgtLeverandør)); }
}
public ObservableCollection<ClientLeverandor> Leverandører
{
    get { return _leverandører; }
    private set { SetProperty(ref _leverandører, value, nameof(Leverandører)); }
}
public ListCollectionView LeverandørView
{
    get { return _leverandørView; }
    set { SetProperty(ref _leverandørView, value, nameof(LeverandørView)); }
}

Command Implementation

using (BusyIndicator.ShowInScope(Strings.HenterData_BusyText))
{
    var leverandører = await SøgLeverandører(Supplier);

    if (leverandører.Any())
    {
        Leverandører.Clear();
        foreach (var lev in leverandører) Leverandører.Add(lev);
        ValgtLeverandør = Leverandører[1];

        SuppliersAdded?.Invoke();
    }
}
JesperGJensen
  • 403
  • 8
  • 24
  • What if you comment the command's code? – Maxim Aug 22 '17 at 14:31
  • The focus implementation is totally awful thing in WPF. Of course there are helper methods, logical/keyboard focus, scopes, etc, but it is really hard to make all this crap working. Your best bet is to deal with focus manually in code behind (in MVVM world we are using [attached behaviors](https://stackoverflow.com/a/1356781/1997232)). – Sinatr Aug 22 '17 at 14:39
  • Thanks for the link Sinatr. I am currently preparing to try and debug the .Net framework as mentioned in the link and later i will look into the Attached Behavior Suggesion. – JesperGJensen Aug 22 '17 at 15:03

1 Answers1

0

I was unable to find an explanation for why KeyboardFocus land on my window or why my attempts to set the focus did not have effect.

But i was finally able to find a solution, where my attempt worked.

I used a Dispatcher with BackgroundPriority to invoke my method to set focus after whatever was setting focus to the window. This worked for both Keyboard and Mouse input.

    private void ViewModel_SuppliersAdded()
    {
        Dispatcher.BeginInvoke(new Action(SetFocusToFirstRow), DispatcherPriority.Background);
    }
JesperGJensen
  • 403
  • 8
  • 24