I have a WPF page that contains several out of the box controls with the tab order set.
I have a custom control (NumericSpinner) that contains: border/grid/text box/2 Repeatbuttons (up/down).
Two issues:
1) when I am in the textbox for the custom selector control, I cannot tab out of it to other controls on the page. However after clicking on one of the up/down arrows, I am able to tab over to other controls.
2) I am unable to tab into the textbox of the custom control in order. It is only after I have tabbed through all of the controls, that the cursor lands in the text box (and cannot tab out).
Context:
<ComboBox Margin="97,315,21,0" Name="txtdweldatcdu" Style="{StaticResource fieldComboBoxStyle}" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left" VerticalAlignment="Top" TabIndex="10" />
<WpfControls:NumericSpinner Margin="97,338,21,0" Name="txtdweldatpctcomplete" HorizontalAlignment="Left" VerticalAlignment="Top" AllowNegativeValues="True" MaxValue="100" TabIndex="11" />
<ComboBox Margin="97,363,21,0" Name="txtdweldatclass" Style="{StaticResource fieldComboBoxStyle}" IsSynchronizedWithCurrentItem="True" HorizontalAlignment="Left" VerticalAlignment="Top" TabIndex="12" />
Portion of the custom control:
<Border BorderThickness="1" BorderBrush="Gray" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top" Height="20" Width="117">
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="98"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBox Name="valueText"
BorderThickness="0"
Grid.RowSpan="2"
Style="{StaticResource spinnerTextBoxStyle}"
PreviewKeyDown="valueText_PreviewKeyDown"
PreviewTextInput="valueText_PreviewTextInput"
TextChanged="valueText_TextChanged"
IsReadOnly="{Binding ElementName=Spinner, Path=IsReadOnly}"
Text="{Binding ElementName=Spinner, Path=Value, Mode=TwoWay}"
KeyboardNavigation.IsTabStop="True"
AcceptsTab="True"/>
<RepeatButton Name="upButton" Style="{StaticResource spinnerRepeatButtonStyle}" Click="upButton_Click" Grid.Column="1" Grid.Row="0" Height="10" Width="18" VerticalAlignment="Top" HorizontalAlignment="Right" HorizontalContentAlignment="Center">
<Polygon HorizontalAlignment="Center" Points="3,2 2,3 4,3" Fill="Black" Stretch="Uniform" Stroke="Black" StrokeThickness="0" />
</RepeatButton>
<RepeatButton Name="downButton" Style="{StaticResource spinnerRepeatButtonStyle}" Click="downButton_Click" Grid.Column="1" Grid.Row="1" Height="10" Width="18" VerticalAlignment="Top" HorizontalAlignment="Right" HorizontalContentAlignment="Center">
<Polygon HorizontalAlignment="Center" Points="2,2 4,2 3,3" Fill="Black" Stretch="Uniform" Stroke="Black" StrokeThickness="0" />
</RepeatButton>
</Grid>
</Border>
The custom control consists of the xaml and code-behind file.
Parent xaml page, containing all controls is loaded dynamically and contains no code-behind.
In the constructor for the custom control, I have set the following as a test:
valueText.TabIndex = 3;
this.TabIndex = 3;
The fourth time I tab, I actually get the cursor into the text field, however I cannot tab out of it.
With this in mind, the first step would be to create a control parameter that I can pass a tab order number that would get set in the control's codebehind.
I created a CustomTabIndex property:
/// <summary>
/// Custom tab index property
/// </summary>
public int CustomTabIndex
{
get { return (int)GetValue(CustomTabIndexProperty); }
set { SetValue(CustomTabIndexProperty, value); }
}
public static readonly DependencyProperty CustomTabIndexProperty =
DependencyProperty.Register("CustomTabIndex", typeof(int), typeof(NumericSpinner));
And in the xaml, when I try to set CustomTabIndex="3", I receive the error:
The property 'CustomTabIndex' was not found in type 'NumericSpinner'.
Some assistance would be appreciated.
I've tried using the selected answer's
GotFocus
event, but it doesn't work for me, it seems to disable the tab navigation altogether, even though the firstTabStop
is indeed selected.What worked for me was using the
WindowActivated
event and use the same command there:I hope it might help someone.
I have an answer to the first one... In your static constructor for your CustomControl add the following
That should let you tab in and out of the control and allow you to set a tab index for each of the children of your custom control.
As for your second question, I'm working on figuring out the same thing. I think it has to due with the fact that your custom control has Focusable = False. But setting this to true will make the control get focus not the actual children. I think what might be required is an event handler on your CustomControl for the GotFocus event. When the control gets focus then do a
and that should move the focus to the child elements.
I'll post a follow up when I figure out the proper way of doing it.
Update
So for your second point.
Make sure you set focusable to false and the TabNavigationProperty like so in the static constructor for your control
This will allow the control to work as expected and respect the Tab Order on the control and also all the children. Make sure that in your style you don't set the Focusable or TabNavigation properties.
Raul
HaxElit's answer works unless we want to use labels to focus our control by Alt + hotkey like this:
So my final solution is as follows:
Raul answered the primary issue - being able to tab into the text box of a custom control. The secondary problem was not being able to tab out of the text box.
The issue with this control was that its textbox contains a keypress handler:
The handler only allows certain keys to be pressed within the textbox:
I simply had to add the allowable TAB keystroke and the custom control works fine:
I don't have a complete solution for you, but the following four things should be checked for tab-cycling:
I could imagine that the IsFocusScope would be interesting.