views:

1869

answers:

3

In this example window, tabbing through goes from the first textbox, to the last textbox and then to the expander header.

<Window x:Class="ExpanderTab.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    FocusManager.FocusedElement="{Binding ElementName=FirstField}">
    <StackPanel>
     <TextBox TabIndex="10" Name="FirstField"></TextBox>
     <Expander TabIndex="20" Header="_abc">
      <TextBox TabIndex="30"></TextBox>
     </Expander>
     <TextBox TabIndex="40"></TextBox>
    </StackPanel>
</Window>

Obviously, I'd like this to go First text box, expander header, then last textbox. Is there an easy way to assign a TabIndex to the header of the expander?

I've tried forcing the expander to be a tabstop using KeyboardNavigation.IsTabStop="True", but that makes the whole expander get focus, and the whole expander doesn't react to the spacebar. After two more tabs, the header is again selected and I can open it with the spacebar.

Edit: I'll throw a bounty out there for anyone who can come up with a cleaner way to do this - if not, then rmoore, you can have the rep. Thanks for your help.

+3  A: 
rmoore
Yeah, I've been playing around with my own ControlTemplate, but it's an absolute beast. Like you said, there's got to be a better way.
Eclipse
+3  A: 

The following code will work even without the TabIndex properties, they are included for clarity about the expected tab order.

<Window x:Class="ExpanderTab.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" FocusManager.FocusedElement="{Binding ElementName=FirstField}">
    <StackPanel>
        <TextBox TabIndex="10" Name="FirstField"></TextBox>
        <Expander TabIndex="20" Header="Section1" KeyboardNavigation.TabNavigation="Local">
            <StackPanel KeyboardNavigation.TabNavigation="Local">
                <TextBox TabIndex="30"></TextBox>
                <TextBox TabIndex="40"></TextBox>
            </StackPanel>
        </Expander>
        <Expander TabIndex="50" Header="Section2" KeyboardNavigation.TabNavigation="Local">
            <StackPanel KeyboardNavigation.TabNavigation="Local">
                <TextBox TabIndex="60"></TextBox>
                <TextBox TabIndex="70"></TextBox>
            </StackPanel>
        </Expander>
        <TextBox TabIndex="80"></TextBox>
    </StackPanel>
</Window>
John JJ Curtis
Very cool, is there a way to have it respect the TabIndex when expanded as well?
rmoore
I'll look into that and update this answer once I have it
John JJ Curtis
Very nice so far!
Eclipse
Got it working completely, tabs work as expected in all scenarios now.
John JJ Curtis
It's only working if the TabIndex's are set in order, like above. I think that's good for 99% of the cases, but it isn't complete.
rmoore
@rmoore - what tab indexes are you seeing a problem with?
John JJ Curtis
Nice -- appears to work even when you drop the explict TabIndex values.
micahtan
@Jeff Johnson if the Expander's TabIndex is greater then an item's TabIndex, and/or if there is an item outside the Expander with a TabIndex of a value in between or lower then that of items in the expander. The Local setting on the StackPanel is forcing it to tab through the entire StackPanel before escaping. Though, as I mentioned I don't really see it as an issue, I can't even think of any examples where I would want that backwards behavior off hand.
rmoore
A: 

Hi,Johnson

Your xaml works fine for the above scenario. But I have encountered another similar issue about tab navigation in expader, could you help to take a look? Thanks.

The issue I encountered is that if rewrite the template of expander, how can I keep the tab navigation behavior, which is we should focus on the content of expander first, then navigate to the header of expander after the last elemement of the content.

The below is a simple xaml which is about my expander's template(just for demo, and I find the KeyboardNavigation.TabIndex won't work.):

        <ControlTemplate x:Key="expander" TargetType="{x:Type Expander}">
        <StackPanel>
            <DockPanel>
                <ToggleButton Content="^" KeyboardNavigation.TabIndex="1" />
                <StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
                    <Button x:Name="btn1" Content="Button1" KeyboardNavigation.TabIndex="2" />
                    <Button x:Name="btn2" Content="Button2" KeyboardNavigation.TabIndex="3" />
                </StackPanel>
            </DockPanel>
            <ContentPresenter KeyboardNavigation.TabIndex="0" />
        </StackPanel>
    </ControlTemplate>
Levin
@Levin - you'll be more likely to get a response if you ask your own question (and reference this question with a link in yours)
Eclipse