Discussion Custom control tab order not working

  • Tuesday, July 29, 2008 9:09 PM
     
      Has Code
    A bit of background first of all...

    On a WPF user control, I have a ListBox that I use to display rows of data. I use a DataTemplate to display the data in a non-edit mode, and a ControlTemplate to display the data in an edit mode. I wrap the editable row in a Label control to allow me to handle certain events.

    The problem is this: One of the controls I use to display/edit the data in the editable row is a custom datepicker control. For some reason, no matter what tab index I give it, it gets skipped when I tab through the controls in the row until after all the other controls have been tabbed over - so it always gets tabbed into last, even though it is physically located in the middle of the row and also has a tab index that reflects that.

    Here is a snippet of the XAML code that shows the ControlTemplate used for the row (please forgive the length of the snippet, but I want to provide as clear a picture as possible):

    <Style x:Key="SessionListItemContainerStyle" TargetType="{x:Type ListBoxItem}"
                <Setter Property="Background" Value="Transparent"/> 
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 
                <Setter Property="VerticalContentAlignment" Value="Top"/> 
                <Setter Property="Padding" Value="0,0,0,0"/> 
                <Setter Property="Margin" Value="0,0,0,0"/> 
                <Setter Property="Template"
                    <Setter.Value> 
                        <ControlTemplate TargetType="{x:Type ListBoxItem}"
                            <Label x:Name="lblContainer"                             
                                MouseDoubleClick="lblContainer_MouseDoubleClick" 
                                KeyUp="OnEditRowKeyUp" 
                                HorizontalAlignment="Stretch" 
                                HorizontalContentAlignment="Stretch" 
                                LostFocus="lblContainer_LostFocus" 
                                IsTabStop="False" 
                                KeyboardNavigation.TabNavigation="Cycle" 
                            > 
     
                                <Grid 
                                    x:Name="dockPanel" 
                                    Width="Auto" 
                                    Height="Auto" 
                                    Margin="0,0,-1,0" 
                                    HorizontalAlignment="Stretch" 
                                    Background="#00FFFFFF" 
                                    Focusable="True" 
                                    LostFocus="lblContainer_LostFocus" 
                                > 
                                    <Grid.ColumnDefinitions> 
                                        <ColumnDefinition Width="Auto"/> 
                                        <ColumnDefinition Width="*"/> 
                                        <ColumnDefinition Width="20"/> 
                                    </Grid.ColumnDefinitions> 
     
                                    <DockPanel 
                                        x:Name="rowEdit" 
                                        Height="40" 
                                        Grid.Column="0" 
                                        HorizontalAlignment="Stretch" 
                                        Margin="0,0,5,0" 
                                        VerticalAlignment="Top" 
                                        Visibility="Collapsed" 
                                    > 
     
                                        <!--EVENT SESSIONS--> 
                                        <TextBox 
                                            x:Name="txtEditableSessionName" 
                                            Width="{StaticResource widthSessionName}" 
                                            Height="25" 
                                            Margin="10,0,0,0" 
                                            DockPanel.Dock="Left" 
                                            Style="{StaticResource SimpleTextBox}" 
                                            Text="{Binding Path=Name}" 
                                            LostFocus="OnNameChanged" 
                                            TextChanged="txtEditableSessionName_TextChanged" 
                                            MaxLength="50" 
                                            IsTabStop="True" 
                                            TabIndex="0" 
                                        /> 
                                        <!--/EVENT SESSIONS--> 
     
                                        <!--CONDUCTING--> 
                                        <ComboBox 
                                            Width="{StaticResource widthConducting}" 
                                            Height="25" 
                                            Margin="5,0,0,0" 
                                            DockPanel.Dock="Left" 
                                            ItemContainerStyle="{DynamicResource SimpleComboBoxItem}" 
                                            Style="{DynamicResource SimpleComboBox}" 
                                            ItemsSource="{Binding Path=Session.PossibleConductors}" 
                                            DisplayMemberPath="FullName" 
                                            SelectedItem="{Binding Path=Session.Conductor}" 
                                            x:Name="cmbConducting" 
                                            SelectionChanged="OnSessionDataChanged" 
                                            IsTabStop="True" 
                                            TabIndex="1" 
                                        /> 
                                        <!--CONDUCTING--> 
     
                                        <!--LOCATION--> 
                                        <ComboBox 
                                            Width="{StaticResource widthLocation}" 
                                            Height="25" 
                                            Margin="5,0,0,0" 
                                            DockPanel.Dock="Left" 
                                            ItemContainerStyle="{DynamicResource SimpleComboBoxItem}" 
                                            Style="{DynamicResource SimpleComboBox}" 
                                            ItemsSource="{Binding Path=Session.PossibleOverflowLocationsSorted}" 
                                            DisplayMemberPath="DisplayName" 
                                            SelectedItem="{Binding Path=Session.Location}" 
                                            x:Name="cmbLocation" 
                                             
                                            IsTabStop="True" 
                                            TabIndex="2" 
                                        /> 
                                        <!--/LOCATION--> 
     
                                        <!--DATE--> 
                                        <UI:DatePicker 
                                            x:Name="dpSessionDate" 
                                            Title="" 
                                            Margin="5,0,0,0" 
                                            DockPanel.Dock="Left" 
                                            VerticalAlignment="Center" 
                                            DateChanged="OnDateChanged" 
                                            Date="{Binding Path=SessionDate}" 
                                            IsTabStop="True" 
                                            TabIndex="3" 
                                        /> 
                                        <!--/DATE--> 
     
                                        <!--START--> 
                                        <ComboBox 
                                            x:Name="cmbStartDateTime" 
                                            Width="{StaticResource widthStart}" 
                                            Height="25" 
                                            Margin="5,0,0,0" 
                                            DockPanel.Dock="Left" 
                                            Style="{DynamicResource SimpleComboBox}" 
                                            ItemContainerStyle="{DynamicResource SimpleComboBoxItem}" 
                                            ItemsSource="{Binding Path=Session.DefaultTimes}" 
                                            SelectedItem="{Binding Path=Session.StartTimeAMPM}" 
                                            SelectionChanged="OnSessionDataChanged" 
                                            IsTabStop="True" 
                                            TabIndex="4" 
                                        /> 
                                        <!--/START--> 
     
                                        <!--DURATION--> 
                                        <ComboBox 
                                            x:Name="cmbDuration" 
                                            Width="{StaticResource widthDuration}" 
                                            Height="25" 
                                            Margin="5,0,0,0" 
                                            DockPanel.Dock="Left" 
                                            ItemContainerStyle="{DynamicResource SimpleComboBoxItem}" 
                                            Style="{DynamicResource SimpleComboBox}" 
                                            ItemsSource="{Binding Path=Session.DefaultDurationStrings}" 
                                            Text="{Binding Path=Session.DurationHHMM}" 
                                            SelectionChanged="OnSessionDataChanged" 
                                            IsEditable="True" 
                                            LostFocus="cmbDuration_LostFocus" 
                                            IsTabStop="True" 
                                            TabIndex="5" 
                                        /> 
                                        <!--/DURATION--> 
     
                                    </DockPanel> 
     
                                    <ContentPresenter x:Name="rowView" Grid.Column="0" Visibility="Visible" /> 
     
                                    <Button 
                                        x:Name="deleteRecordButton" 
                                        Width="15" 
                                        Height="15" 
                                        Grid.Column="2" 
                                        HorizontalAlignment="Right" 
                                        Margin="0,0,5,0" 
                                        VerticalAlignment="Center" 
                                        Content="" 
                                        Style="{DynamicResource DeleteRecordButtonStyle}" 
                                        Visibility="Hidden" 
                                        IsTabStop="True" 
                                        TabIndex="6" 
                                    /> 
                                </Grid> 
     
                            </Label> 
     
                            <ControlTemplate.Triggers> 
                                <Trigger Property="IsSelected" Value="true"
                                    <Setter TargetName="deleteRecordButton" Property="Visibility" Value="Visible"/> 
                                    <Setter TargetName="dockPanel" Property="Background" Value="#FFD8E9EC"/> 
                                </Trigger> 
                                <Trigger Property="IsSelected" Value="false"
                                    <Setter TargetName="deleteRecordButton" Property="Visibility" Value="Hidden"/> 
                                </Trigger> 
                                <MultiTrigger> 
                                    <MultiTrigger.Conditions> 
                                        <Condition Property="IsSelected" Value="true"/> 
                                        <Condition Property="Selector.IsSelectionActive" Value="false"/> 
                                    </MultiTrigger.Conditions> 
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
                                </MultiTrigger> 
                                <Trigger Property="IsEnabled" Value="false"
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
                                </Trigger> 
                            </ControlTemplate.Triggers> 
     
                        </ControlTemplate> 
                    </Setter.Value> 
                </Setter> 
            </Style> 

    The control named, "UI:DatePicker", is the control in question. Note that it is the fourth of seven controls and has a TabIndex of 3. The order in which I expect the tabbing to occur is:

    0 - "txtEditableSessionName" TextBox
    1 - "cmbConducting" ComboBox
    2 - "cmbLocation" ComboBox
    3 - "dpSessionDate" UI:DatePicker
    4 - "cmbStartDateTime" ComboBox
    5 - "cmbDuration" ComboBox
    6 - "deleteRecordButton" Button

    The order that actually happens though is:

    0 - "txtEditableSessionName" TextBox
    1 - "cmbConducting" ComboBox
    2 - "cmbLocation" ComboBox
    3 - "cmbStartDateTime" ComboBox
    4 - "cmbDuration" ComboBox
    5 - "deleteRecordButton" Button
    6 - The Label that contains the child controls
    7 - "dpSessionDate" UI:DatePicker

    I have moved the physical position of UI:DatePicker control, as well as modified its TabIndex, but still get the same behavior: it always gets skipped until the very end.

    Does anyone have any idea what the cause of the problem (and solution) could be?

    Thank you.
    • Changed Type Marco Zhou Wednesday, August 06, 2008 10:02 AM OP doesn't revert back
    •  

All Replies

  • Monday, August 04, 2008 2:32 AM
     
     
    System.Windows.Controls.Control.IsTabStop property could control if a specified control will be considered during tab navigation.

    Hope this helps
  • Wednesday, August 06, 2008 10:02 AM
     
     

    We are changing the issue type to “Comment” because you have not followed up with the necessary information. If you have more time to look at the issue and provide more information, please feel free to change the issue type back to “Question” by clicking the "Options" link at the top of your post, and selecting "Change Type" menu item from the pop menu. If the issue is resolved, we will appreciate it if you can share the solution so that the answer can be found and used by other community members having similar questions.

     

    Thank you!

  • Thursday, January 27, 2011 10:28 PM
     
     
    Just for the sake of making this page into useful information, I will share my experience. I had a similar problem and I found that setting IsTabStop = true on my custom control miraculously fixed the tab order.  I don't really understand that because the control was already behaving like a tab stop, it was just in the wrong tab order.  O well, whatever works!  This won't be the weirdest thing I've ever seen.  
  • Saturday, March 31, 2012 10:18 AM
     
     
    Thanks mate!!
    I'll try and let you all know!!