I have an application in WPF that is to be used exclusively by the keyboard, so we are really picky about focus behavior.
So, we get a PreviewLostKeyboardFocus on a textbox. Under certain circumstances we disable the next 5 fields and want the focus to go to the field after that. One might assume that the focus would do that, finding the next focusable field, this is what happens if I didn’t disable the fields in the preview event. It doesn’t, it keeps the focus on the first textbox.
I’ve tried forcing the focus with Keyboard.Focus(uielement) but nothing happens. It seems that the next focus target is already commited.
How can I make this happen, or am I “doing it wrong”? I am not in a position to change the requirement that specifies this behavior; I know that it is somewhat strange.
Thanks.
Edit: here is a small app that shows this behavior.
XAML:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
FocusManager.FocusedElement="{Binding ElementName=textBox0}"
>
<StackPanel>
<TextBox Height="23" Margin="5" Name="textBox0" Width="120" />
<TextBox Height="23" Margin="5" Name="textBox1" Width="120" PreviewLostKeyboardFocus="textBox1_PreviewLostKeyboardFocus"/>
<TextBox Height="23" Margin="5" Name="textBox2" Width="120" />
<TextBox Height="23" Margin="5" Name="textBox3" Width="120" />
<TextBox Height="23" Margin="5" Name="textBox4" Width="120" />
</StackPanel>
</Window>
Codebehind:
using System.Windows;
using System.Windows.Input;
namespace WpfApplication4 {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void textBox1_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
textBox2.IsEnabled = false;
textBox3.IsEnabled = false;
}
}
}
An obvious thing to try (at least for me) was to put Keyboard.focus(textBox4); in the PreviewLostKeyboardFocus event handler. It of course didn’t work, it causes a loop that fires the PreviewLostKeyboardFocus event again….
Yet another edit:
I’ve found that using breakpoints in textBox1_PreviewLostKeyboardFocus() will sometimes cause it to behave, or sometimes not even disable the 2nd and 3rd text boxes. I’m thinking of a race/threading problem.
I am not sure what exactly is causing this behavior but from past experience the WPF focus system is extremely unreliable after changing the controls in any way or when setting focus manually.
However, using a Dispatcher to perform focus changes after WPF caught up with the changes to the controls, often solves the problem.
This works fine in my testing