I have a WPF form with which I would like to have arrow-key navigation. The current system is off, even though I have successfully specified the tab navigation order. I have two rows of three radio buttons. When I am on the middle button, top row, I should be able to hit the left arrow and select the first button of the top row; instead it selects the first button, bottom row. How do I correct this?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="80*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15*"/>
<RowDefinition Height="15*"/>
<RowDefinition Height="15*"/>
<RowDefinition Height="30*"/>
<RowDefinition Height="25*"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="Who:" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,5,0" FontSize="12"/>
<Label Grid.Column="0" Grid.Row="1" Content="Caller:" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,5,0" />
<Label Grid.Column="0" Grid.Row="2" Content="Office:" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,5,0" />
<Label Grid.Column="0" Grid.Row="3" Content="Name:" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,5,0" />
<Button Grid.Column="0" Grid.Row="4" Content="Find" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="0,0,0,0" Width="50" Command="{Binding Path=FindCommand}" IsDefault="True" Click="Button_Click" TabIndex="9" />
<Grid Grid.Column="1" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Content="All People" Grid.Column="0" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsPersonAll}" TabIndex="3" />
<RadioButton Content="Users Only" Grid.Column="1" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsPersonUser}" TabIndex="4" />
<RadioButton Content="Admin Only" Grid.Column="2" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" TabIndex="5" />
</Grid>
<Grid Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Content="Off Campus" Grid.Column="0" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsCallerOff}" TabIndex="6" />
<RadioButton Content="Admin" Grid.Column="1" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsCallerOnAd}" TabIndex="7" />
<RadioButton Content="User" Grid.Column="2" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top" TabIndex="8" />
</Grid>
<ComboBox
Grid.Column="1" Grid.Row="2"
Height="25" HorizontalAlignment="Stretch"
Margin="0,0,0,0" VerticalAlignment="Top"
ItemsSource="{Binding Path=Offices}"
SelectedItem="{Binding Path=Office}" TabIndex="2" />
<Grid Grid.Column="1" Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="55*"/>
<RowDefinition Height="45*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<TextBox Name="lName" Grid.Column="0" Grid.Row="0" Margin="0,0,5,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="22" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged}" TabIndex="0" />
<TextBox Grid.Column="1" Grid.Row="0" Margin="5,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="22" Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}" TabIndex="1" />
<Label Grid.Column="0" Grid.Row="1" Content="Last Name" HorizontalAlignment="Left" Margin="-5,-5,0,0" VerticalAlignment="Top" />
<Label Grid.Column="1" Grid.Row="1" Content="First Name" HorizontalAlignment="Left" Margin="0,-5,0,0" VerticalAlignment="Top" />
<Label Grid.Row="2" Grid.ColumnSpan="2" Content="Please supply search information in Department or Name." Foreground="Red" HorizontalAlignment="Stretch" Margin="-5,-5,0,0" VerticalAlignment="Top" Height="26" Visibility="{Binding Path=ErrVisibility}"/>
</Grid>
</Grid>
It's also for me kind of odd behaviour and after playing around with it i can tell you that it's caused by the HorizontalAlignment property, but i can't really explain why. Maybe someone else can shed some light on that.
Some more information:
In your case controls are focused alphabetically by the content property. You can easily test that by changing
<RadioButton Content="All People" Grid.Column="0" HorizontalAlignment="Left"
to
<RadioButton Content="Pall People" Grid.Column="0" HorizontalAlignment="Left"
After changing, controls are now focused correctly from right to left on first line because of alphabetical order: Users -> Pall People -> Off Campus.
As i was not aware of this behaviour i tried to reproduce by creating a new project with following XAML, but the behaviour of arrow keys was as expected, focusing the next neigbour in direction of the arrow key:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0" Content="All People"></RadioButton>
<RadioButton Grid.Column="1" Content="Users Only"></RadioButton>
<RadioButton Grid.Column="2" Content="Admin Only"></RadioButton>
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0" Content="Off Campus"></RadioButton>
<RadioButton Grid.Column="1" Content="Admin"></RadioButton>
<RadioButton Grid.Column="2" Content="User"></RadioButton>
</Grid>
</Grid>
So i removed properties of the radio buttons of your xaml till i finally hit the point by removing HorizontalAlignment.
That XAML is now working as expected, at least for the radio buttons:
<Grid Grid.Column="1" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Content="All People" Grid.Column="0" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsPersonAll}" TabIndex="3" />
<RadioButton Content="Users Only" Grid.Column="1" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsPersonUser}" TabIndex="4" />
<RadioButton Content="Admin Only" Grid.Column="2" Margin="0,5,0,0" VerticalAlignment="Top" TabIndex="5" />
</Grid>
<Grid Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Content="Off Campus" Grid.Column="0" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsCallerOff}" TabIndex="6" />
<RadioButton Content="Admin" Grid.Column="1" Margin="0,5,0,0" VerticalAlignment="Top" IsChecked="{Binding Path=IsCallerOnAd}" TabIndex="7" />
<RadioButton Content="User" Grid.Column="2" Margin="0,5,0,0" VerticalAlignment="Top" TabIndex="8" />
</Grid>