In the project I am building I have a TabControl
in which I want to display a range of tabs through an ItemsSource
. I also need to have a few "overview" tabs at the beginning of the TabControl
, that cannot be located in ItemsSource
.
What is the best way to achieve this, the only way I can think of is to have my overview tabs in my XAML and to just add tab items manually through code instead of using ItemSource
is this the best way to go about it.
You can use CompositeCollection
(MSDN) to accomplish this:
<Window.Resources>
<CollectionViewSource x:Key="ExistingTabs" Source="{Binding ExistingTabs}"/>
</Window.Resources>
<TabControl>
<TabControl.ItemsSource>
<CompositeCollection>
<TabItem>SpecialItem</TabItem>
<CollectionContainer Collection="{Binding Source={StaticResource ExistingTabs}}"/>
</CompositeCollection>
</TabControl.ItemsSource>
</TabControl>
For anyone finding the way of using HeaderTemplate / ContentTemplate with CollectionContainer:
First Add Type Property in ViewModel
public Type Type { get { return this.GetType(); } }
Use Style.Triggers to set HeaderTemplate / ContentTemplate for the dynamic tabs identified by the Type property
<Window x:Class="TabDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TabDemo"
xmlns:vm="clr-namespace:TabDemo.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
d:DataContext="{d:DesignInstance vm:TabViewModel}">
<Window.Resources>
<CollectionViewSource x:Key="ExistingTabs" Source="{Binding ExistingTabs}"/>
<DataTemplate x:Key="TemplateForTheHeader" DataType="{x:Type vm:TabViewModel}">
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
<DataTemplate x:Key="TemplateForTheContent" DataType="{x:Type vm:TabViewModel}">
<DockPanel>
<DataGrid ItemsSource="{Binding Data}"></DataGrid>
</DockPanel>
</DataTemplate>
<Style x:Key="TabItemStyle" TargetType="TabItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Type}" Value="{x:Type vm:TabViewModel}">
<Setter Property="HeaderTemplate" Value="{StaticResource TemplateForTheHeader}" />
<Setter Property="ContentTemplate" Value="{StaticResource TemplateForTheContent}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TabControl Grid.Row="1" ItemContainerStyle="{StaticResource TabItemStyle}">
<TabControl.ItemsSource>
<CompositeCollection>
<TabItem Header="Fixed Header">
<TabItem.Content>
<TextBlock Text="Fixed Content"/>
</TabItem.Content>
</TabItem>
<CollectionContainer Collection="{Binding Source={StaticResource ExistingTabs}}"/>
</CompositeCollection>
</TabControl.ItemsSource>
</TabControl>
</Grid>
</Window>
Referencing Anderson Imes's answer: https://stackoverflow.com/a/1348369/1196637
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With