Kantine
Kantine

Reputation: 67

How to split a WPF TabControl's tabs on left and right?

I would like to have a TabControl with half of the tabs on the left, the other half on the right and the content presenter in the middle. See picture below.

enter image description here

I tried to edit the TabControl ControlTemplate and replace the TabPanel with a DockPanel with two StackPanels as follows:

<TabControl ItemsSource="{Binding Sequences}" SelectedIndex="0">
    <TabControl.Style>
        <Style TargetType="TabControl">
            <Setter Property="OverridesDefaultStyle"
                    Value="True" />
            <Setter Property="SnapsToDevicePixels"
                    Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabControl">
                        <DockPanel>
                            <StackPanel DockPanel.Dock="Left" IsItemsHost="True" Width="100"/>
                            <StackPanel DockPanel.Dock="Right" IsItemsHost="True" Width="100"/>
                            <ContentPresenter ContentSource="SelectedContent" Margin="100,5,5,5" />
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.Style>
    <!-- ... -->
</TabControl>

But I get 6 tabs on each side with non working tabs on the left (there is no header and nothing displayed on the content presenter when I click on them).

How can I split TabControl's ItemsSource in my two StackPanels ?

Upvotes: 4

Views: 748

Answers (2)

Denis Schaf
Denis Schaf

Reputation: 2739

Did not want to override my previous answer as it still a valid answer for those who dont want to bind the itemssource. I was able to make it look correct but the buttons dont work. Maybe you have an idea how to go on from here yourself:

enter image description here

    <TabControl ItemsSource="{Binding Controls}">
        <TabControl.Style>
            <Style TargetType="TabControl" x:Name="myName" >
                <Style.Resources>
                    <conv:ObservableCollectionSplitter x:Key="ObsColSplt"/>
                </Style.Resources>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="TabControl">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="100"/>
                                    <ColumnDefinition/>
                                    <ColumnDefinition Width="100"/>
                                </Grid.ColumnDefinitions>
                                <ItemsControl Grid.Column="2" ItemsSource="{TemplateBinding ItemsSource, Converter={StaticResource ObsColSplt}, ConverterParameter=even}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel IsItemsHost="True"/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                                <ItemsControl Grid.Column="0"  ItemsSource="{TemplateBinding ItemsSource, Converter={StaticResource ObsColSplt}, ConverterParameter=uneven}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel IsItemsHost="True"/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                                <ContentPresenter Grid.Column="1" ContentSource="SelectedContent"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </TabControl.Style>
       
    </TabControl>

and the converter (not my proudest bit of code):

public class ObservableCollectionSplitter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            ObservableCollection<TabItem> partialCollection = null;
            if (value != null)
            {
                partialCollection = new ObservableCollection<TabItem>();
                ObservableCollection<TabItem> inputCollection = (value as ObservableCollection<TabItem>);
                int a = 0;
                if (parameter.ToString() == "even")
                {
                    a = 1;
                }
                for (int i = a; i < inputCollection.Count; i = i + 2)
                {
                    partialCollection.Add(inputCollection[i]);
                }
            }
            return partialCollection;

        }//END Convert 

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }//END ConvertBack

    }//END class BooleanInverter : IValueConverter 

Upvotes: 0

Denis Schaf
Denis Schaf

Reputation: 2739

Not exactly sure why this is working but it is. I stumbled across it by trying to solve this for you.

enter image description here

<TabControl>
    <TabControl.Style>
        <Style TargetType="TabControl" x:Name="myName">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabControl">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"/>
                                <ColumnDefinition/>
                                <ColumnDefinition Width="100"/>
                            </Grid.ColumnDefinitions>
                            <StackPanel Name="stk" Grid.Column="0" IsItemsHost="True" Width="100"/>
                            <ItemsControl Grid.Column="2"  ItemsSource="{Binding ElementName=stk, Path=Children}">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <StackPanel/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>
                            <ContentPresenter Grid.Column="1" ContentSource="SelectedContent"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.Style>
    <TabItem Header="One">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">1</TextBlock>
    </TabItem>
    <TabItem Header="two">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">2</TextBlock>
    </TabItem>
    <TabItem Header="three">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">3</TextBlock>
    </TabItem>
    <TabItem Header="four">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">4</TextBlock>
    </TabItem>
</TabControl>

If somebody could tell me how the framework decides which item to place where i'd be very courios!

Upvotes: 1

Related Questions