Recently, I have been using WPF to give a .NET desktop application its own customized look and feel that matches my client’s product branding.
In one of the workflows I implemented last week, the user inputs a 4-digit passcode that allows them to connect to an external device.
Here is a diagram of the workflow we needed to implement:
Instead of one
TextBox control for the entire code, we wanted to have 4 seperate
TextBox controls. This will indicate to the user that they need to have a code with 4 digits. However, it would be very annoying if we made the user tab between each
TextBox as they entered their passcode. Therefore, as the user types in each digit, we will need to automatically move focus to the next
TextBox for them.
Here are the controls I used to achieve this interaction:
I have a grid containing a
TextBlock for the explanation text. The four
TextBlocks are contained in a
StackPanel, and each
TextBlock has a unique
Name. Last comes the
Button for the connection interaction. Each
TextBox has a
Name, as does the
Button. These will become important when we set up the interaction.
Next, in a separate
ResourceDictionary, I created styles for the
Grid and the
TextBoxes. We’ll take a closer look at those in a moment.
How to Set Focus on a TextBox Using Triggers in XAML
This seems like a relatively easy thing to do. The
TextBox Class has an
IsFocused property. So it would be natural to assume that you could just use a
Setter inside a
Trigger on the
TextBox to set
True. However, this doesn’t work.
IsFocused is a read-only property inherited from
UIElement, so it cannot be set with a
Setter. What are we going to do?
Instead of using a
Setter on the
TextBox, we’ll have to use the
FocusManger controls focus within a specific focus scope. So by setting
FocusManager.FocusedElement on our FocusScope, we can acheive focus on a textbox.
Here, I used
DataTriggers on the
Grid that contains all of my controls to detect when a digit was entered into each
TextBox. When a digit is entered into the
TextBox named CodeDigit1, the
Trigger moves the focus to the
TextBox named CodeDigit2. It will continue on down to CodeDigit3 and CodeDigit4, and finally, after all 4 digits are entered, it will give focus to the
ConnectButton at the end. Nifty.
Because of the nature of the workflow in my app, I could use a
Trigger on the
Text.Length like this. Depending on your specific implementation, you may need to choose a different property for your trigger.
I have created a small working demo of this interaction. Click here to download the TextBox Focus Demo.