TaskTabItem Does Not Keep Selection

Ribbon for WPF Forum

Posted 13 years ago by Andy Ver Murlen
Version: 11.1.0545
Platform: .NET 4.0
Environment: Windows 7 (32-bit)
Avatar
When a TaskTabControl is nested inside a TabControl, IsSelected on the TaskTabControl's TaskTabITems is not honored as the user cycles through the tabs of the parent TabControl.

The Odd thing is, if everything remains the same and the TaskTabControl is changed to a BackStage, the problem disappears.

Consider the following code. If you click on the "Two" tab of the parent control, the "Three" tab will be selected on the TaskTabControl, even though IsSelected is set on the "Four" tab. To compound matters, if you click on the "Four" tab in the TaskTabControl, then click on the "One" tab and back to the "Two" tab in the parent tab control, the "Four" tab will no longer be selected.

<Window 
    x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" 
    Height="350" 
    Width="525"
    xmlns:Ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon"
    >
    <Grid>
        <TabControl>
            <TabItem Header="One">
                <Ribbon:TaskTabControl>
                    <Ribbon:TaskTabItem Header="One">
                        <Grid>
                            <TextBlock Text="Tab One Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>

                    <Ribbon:TaskTabItem Header="Two" IsSelected="True">
                        <Grid>
                            <TextBlock Text="Tab Two Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>
                </Ribbon:TaskTabControl>
            </TabItem>
            <TabItem Header="Two">
                <Ribbon:TaskTabControl>
                    <Ribbon:TaskTabItem Header="Three">
                        <Grid>
                            <TextBlock Text="Tab Three Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>

                    <Ribbon:TaskTabItem Header="Four" IsSelected="True">
                        <Grid>
                            <TextBlock Text="Tab Four Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>
                </Ribbon:TaskTabControl>
            </TabItem>
        </TabControl>        
    </Grid>
</Window>
Now consider this code. When the "Two" tab is selected on the parent tab control, the "Four" tab is properly set.

<Window 
    x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" 
    Height="350" 
    Width="525"
    xmlns:Ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon"
    >
    <Grid>
        <TabControl>
            <TabItem Header="One">
                <Ribbon:Backstage>
                    <Ribbon:BackstageTab Header="One">
                        <Grid>
                            <TextBlock Text="Tab One Content" />
                        </Grid>
                    </Ribbon:BackstageTab>

                    <Ribbon:BackstageTab Header="Two" IsSelected="True">
                        <Grid>
                            <TextBlock Text="Tab Two Content" />
                        </Grid>
                    </Ribbon:BackstageTab>
                </Ribbon:Backstage>
            </TabItem>
            <TabItem Header="Two">
                <Ribbon:Backstage>
                    <Ribbon:BackstageTab Header="Three">
                        <Grid>
                            <TextBlock Text="Tab Three Content" />
                        </Grid>
                    </Ribbon:BackstageTab>

                    <Ribbon:BackstageTab Header="Four" IsSelected="True">
                        <Grid>
                            <TextBlock Text="Tab Four Content" />
                        </Grid>
                    </Ribbon:BackstageTab>
                </Ribbon:Backstage>
            </TabItem>
        </TabControl>        
    </Grid>
</Window>

This is also not an issue using standard WPF TabControls nested inside each other.

[Modified at 08/25/2011 03:50 PM]

Comments (8)

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Andy,

It seems to be due to Focusable="True" being set in the TaskTabControl Style. Set it to false and I believe that will work around it for now. We'll remove that setter for the next version.


Actipro Software Support

Posted 13 years ago by Andy Ver Murlen
Avatar
Hi, I did as suggested, with no change. With Focusable set to False, IsSelected is still not maintained while cycling tabs in the parent tab control.

<Window 
    x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" 
    Height="350" 
    Width="525"
    xmlns:Ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon" 
    xmlns:Themes="http://schemas.actiprosoftware.com/winfx/xaml/themes"
    >
    
    <Window.Resources>
        <Style x:Key="TabControlStyle" TargetType="{x:Type Ribbon:TaskTabControl}">
            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static Themes:RibbonCommonDictionary.ApplicationMenuOuterBorderBrushKey}}" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Focusable" Value="False" /> <!-- SET TO FALSE -->
            <Setter Property="Padding" Value="25,0,25,0" />
            <Setter Property="TabStripPlacement" Value="Left" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Ribbon:TaskTabControl}">

                        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                            <DockPanel>

                                <Border DockPanel.Dock="Left">
                                    <Grid>
                                        <Rectangle HorizontalAlignment="Right" Width="1">
                                            <Rectangle.Fill>
                                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                                    <GradientStop Color="#00d7d7d7" Offset="0" />
                                                    <GradientStop Color="#d7d7d7" Offset="0.1" />
                                                    <GradientStop Color="#d7d7d7" Offset="0.9" />
                                                    <GradientStop Color="#00d7d7d7" Offset="1" />
                                                </LinearGradientBrush>
                                            </Rectangle.Fill>
                                        </Rectangle>

                                        <ScrollViewer VerticalScrollBarVisibility="Auto">
                                            <StackPanel Panel.ZIndex="1" IsItemsHost="true" />
                                        </ScrollViewer>
                                    </Grid>
                                </Border>

                                <Border KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.DirectionalNavigation="Contained">
                                    <ContentPresenter x:Name="PART_SelectedContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                                        Margin="{TemplateBinding Padding}" ContentSource="SelectedContent" />
                                </Border>

                            </DockPanel>
                        </Border>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    
    <Grid>
        <TabControl>
            <TabItem Header="One">
                <Ribbon:TaskTabControl Style="{StaticResource TabControlStyle}">
                    <Ribbon:TaskTabItem Header="One">
                        <Grid>
                            <TextBlock Text="Tab One Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>

                    <Ribbon:TaskTabItem Header="Two" IsSelected="True">
                        <Grid>
                            <TextBlock Text="Tab Two Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>
                </Ribbon:TaskTabControl>
            </TabItem>
            <TabItem Header="Two">
                <Ribbon:TaskTabControl Style="{StaticResource TabControlStyle}">
                    <Ribbon:TaskTabItem Header="Three">
                        <Grid>
                            <TextBlock Text="Tab Three Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>

                    <Ribbon:TaskTabItem Header="Four" IsSelected="True">
                        <Grid>
                            <TextBlock Text="Tab Four Content" />
                        </Grid>
                    </Ribbon:TaskTabItem>
                </Ribbon:TaskTabControl>
            </TabItem>
        </TabControl>
    </Grid>
</Window>
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Sorry I thought that had done it but it appears to be the Focusable setting on the TaskTabItems instead. If you explicitly set them to False on your TaskTabItems, I believe it works in your sample.

What seems to be happening from debugging is that focus is moved to the tab by the WPF system and that selects that tab (from other MS internal code). I don't see any difference in setting the Focusable props between the Task and Backstage tab controls either, and I've looked in our templates and code-behind.


Actipro Software Support

Posted 13 years ago by Andy Ver Murlen
Avatar
Setting Focusable to False on the TaskTabItems certainly fixes the IsSelection issue. However, with it set to False, you can't select any other TaskTabItems in the TaskTabControl....
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
You could inject a "dummy" element so focus goes to it when the parent tab is selected instead of to the nested tab control, like:
<Grid>
    <Border Focusable="True" />
    <ribbon:TaskTabControl>...</ribbon:TaskTabControl>
</Grid>


Actipro Software Support

Posted 13 years ago by Andy Ver Murlen
Avatar
I may be misunderstanding you, but that doesn't solve the problem. In the following code, TaskTabItems "ChildTabTwo" and "ChildTabFour" will be properly selected (which is a step forward from the original issue), however, it is not possible to select TaskTabItems "ChildTabOne" or "ChildTabThree".

<Window 
    x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" 
    Height="350" 
    Width="525"
    xmlns:Ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon"
    >       
    <Grid>
        <TabControl>
            <TabItem Header="ParentTabOne">
                <Grid>
                    <Border Focusable="True" />
                    <Ribbon:TaskTabControl>
                        <Ribbon:TaskTabItem Header="ChildTabOne" Focusable="False">
                            <Grid>
                                <TextBlock Text="Tab One Content" />
                            </Grid>
                        </Ribbon:TaskTabItem>

                        <Ribbon:TaskTabItem Header="ChildTabTwo" IsSelected="True" Focusable="False">
                            <Grid>
                                <TextBlock Text="Tab Two Content" />
                            </Grid>
                        </Ribbon:TaskTabItem>
                    </Ribbon:TaskTabControl>
                </Grid>
            </TabItem>
            <TabItem Header="ParentTabTwo">
                <Grid>
                    <Border Focusable="True" />
                    <Ribbon:TaskTabControl>
                        <Ribbon:TaskTabItem Header="ChildTabThree" Focusable="False">
                            <Grid>
                                <TextBlock Text="Tab Three Content" />
                            </Grid>
                        </Ribbon:TaskTabItem>

                        <Ribbon:TaskTabItem Header="ChildTabFour" IsSelected="True" Focusable="False">
                            <Grid>
                                <TextBlock Text="Tab Four Content" />
                            </Grid>
                        </Ribbon:TaskTabItem>
                    </Ribbon:TaskTabControl>
                </Grid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>
[Modified at 08/26/2011 01:47 PM]
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Yes, I meant add the "dummy" control but take back off the Focusable="False" on the tab items.


Actipro Software Support

Posted 13 years ago by Andy Ver Murlen
Avatar
Bingo. It's clumsy, but seems to work.
The latest build of this product (v24.1.2) was released 3 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.