HeaderTemplate for TabControl

Topics: Prism v4 - WPF 4
Apr 30, 2015 at 9:46 PM
Having the following TabControl I am not able to bind the "Caption"-Property to the HeaderTemplate, while it is working as commented for the "Header"-Property. Since i want to provide a Close-Command to close the TabItem, I do need the Header Template.
<TabControl Grid.Row="1" region:RegionManager.RegionName="TabRegion" SelectedItem="{Binding SelectedItem}">
            <TabControl.ItemContainerStyle>
                <Style TargetType="{x:Type TabItem}">
                    <!--<Setter Property="Header" Value="{Binding Content.DataContext.Caption}" />-->
                    <Setter Property="HeaderTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Caption}"/>
                                    <Button Content="X" Command="{Binding RelativeSource=
                                        {RelativeSource FindAncestor,
                                        AncestorType={x:Type TabControl}},
                                        Path= DataContext.CloseTabCommand}"/>
                                </StackPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TabControl.ItemContainerStyle>
        </TabControl>
I'm generating the TabItems as follows:
private void AddTabItem(Type tabItemViewModelType, string caption, string name)
        {
            var existsItem = TabRegion.GetView(name) != null;

            if (!existsItem)
            {
                var view = App.Bootstrapper.Container.Resolve<AdministrationControl>();
                TabItemViewModel tabItemViewModel = (TabItemViewModel)App.Bootstrapper.Container.Resolve(tabItemViewModelType);
                view.DataContext = tabItemViewModel;
                tabItemViewModel.Caption = caption;
                tabItemViewModel.Name = name;
                tabItemViewModel.Visibility = System.Windows.Visibility.Visible;
                TabRegion.Add(view, name);
                TabRegion.Activate(view);
            }
        }
May 1, 2015 at 9:10 AM
<TextBlock Text="{Binding RelativeSource=
                                        {RelativeSource FindAncestor,
                                        AncestorType={x:Type TabItem}},
                                        Path= DataContext.Caption}"/>
Is not working either.
May 1, 2015 at 8:06 PM
The way I normally do it is to set the ItemTemplate on the TabControl itself, that is used for rendering the tab.
May 4, 2015 at 8:44 AM
Could you please provide a sample?

How far does the ItemTemplate differ from the HeaderTemplate? Isn't the ItemTemplate meant to cover the styles for the TabItem-Content?
May 4, 2015 at 12:31 PM
Sorry, did not read closely there, forgot you were talking about a TabControl that is a region, so ItemTemplates don't apply since there is no data binding going on for the items.

Don't know the exact answer off the top of my head, but think the issue is that your {Binding Caption} presumes that the DataContext for the TabItem is the ViewModel itself, which I don't think is the case. The ViewModel would be the DataContext for the View that you plug into the Content of the TabItem, but would not be the DataContext for the TabItem as a whole. So you would need a RelativeSource binding to get to the TabItem, then use a path of Content.DataContext.Caption like your commented out setter.
May 4, 2015 at 6:12 PM
Edited May 4, 2015 at 6:12 PM
Thanks for your input. It lead me right to the core of the problem. In addition I found another post covering a similar problem. I adopted its solution for my problem as follows:
<TabControl.ItemContainerStyle>
                <Style TargetType="{x:Type TabItem}">
                    <Setter Property="Header" Value="{Binding Content.DataContext}"/>
                    <Setter Property="HeaderTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Caption}"/>
                                    <Button Content="X" Command="{Binding RelativeSource=
                                        {RelativeSource FindAncestor,
                                        AncestorType={x:Type TabControl}},
                                        Path= DataContext.CloseTabCommand}"/>
                                </StackPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TabControl.ItemContainerStyle>
Seems like the Header-property is placed somewhere higher in the tree so that i can reference the contents DataContext which makes it available for the HeaderTemplate as well.
May 27, 2015 at 2:01 AM
I too am having this issue but the above code works well. How did you write your CloseTabCommand

Path= DataContext.CloseTabCommand}"/>