views:

1629

answers:

3

I have a custom control that is derived from TabItem, and I want to databind that custom TabItem to a stock TabControl. I would rather avoid creating a new TabControl just for this rare case.

This is what I have and I'm not having any luck getting the correct control to be loaded. In this case I want to use my ClosableTabItem control instead of the stock TabItem control.

<TabControl x:Name="tabCases" IsSynchronizedWithCurrentItem="True" Controls:ClosableTabItem.TabClose="TabClosed" >
        <TabControl.ItemTemplate>
            <DataTemplate DataType="{x:Type Controls:ClosableTabItem}" >
                <TextBlock Text="{Binding Path=Id}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate DataType="{x:Type Entities:Case}">
                <CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>

EDIT: This is what I ended up with, rather than trying to bind a custom control. The "CloseCommand" im getting from a previous question.

<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Border 
                            Name="Border"
                            Background="LightGray"
                            BorderBrush="Black" 
                            BorderThickness="1" 
                            CornerRadius="25,0,0,0"
                            SnapsToDevicePixels="True">
                        <StackPanel Orientation="Horizontal">
                        <ContentPresenter x:Name="ContentSite"
                              VerticalAlignment="Center"
                              HorizontalAlignment="Center"
                              ContentSource="Header"
                              Margin="20,1,5,1"/>
                            <Button 
                                Command="{Binding Path=CloseCommand}"
                                Cursor="Hand"
                                DockPanel.Dock="Right"
                                Focusable="False"
                                Margin="1,1,5,1"
                                Background="Transparent"
                                BorderThickness="0">
                                <Image Source="/Russound.Windows;component/Resources/Delete.png" Height="10" />
                            </Button>
                        </StackPanel>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                            <Setter TargetName="Border" Property="Background" Value="LightBlue" />                            
                            <Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
                            <Setter TargetName="Border" Property="BorderBrush" Value="DarkBlue" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
+1  A: 

You don't want to set the DataType of the DataTemplate in this case. The value of the ItemTemplate property is used whenever a new item needs to be added, and in the case of a tab control it will be used to create a new TabItem. You should declare an instance of your class within the DataTemplate itself:

<TabControl x:Name="tabCases" IsSynchronizedWithCurrentItem="True" Controls:ClosableTabItem.TabClose="TabClosed">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <Controls:ClosableTabItem>
                <TextBlock Text="{Binding Path=Id}" />
            </Controls:ClosableTabItem>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate DataType="{x:Type Entities:Case}">
            <CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

This will cause a new ClosableTabItem to be created whenever a new tab is added to the TabControl.

Update; From your comment, it sounds like that the ItemTemplate controls what is created within the TabItem, rather than changing the TabItem itself. To do what you want to do, but for a TreeView, you would set the HeaderTemplate. Unfortunately, I don't see a HeaderTemplate property of TabControl.

I did some searching, and this tutorial modifies the contents of the tab headers by adding controls to TabItem.Header. Maybe you could create a Style for your TabItems that would add the close button that your class is currently adding?

Andy
I have tried that, and what seems to happen is that my custom control is loaded inside of a stock TabItem. This leaves me with a border around my custom control, as well as my custom control doesn't know how to pass focus through to the stock tabitem.
Russ
A: 

I have exactly this problem, was a solution ever found?

TIA Sam

Sam Martin
A: 

found a way, derive a class from TabControl and override this function, in my case I want the items of the tab control (when bound) to be CloseableTabItems

public class CloseableTabControl : TabControl
    {
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new CloseableTabItem();
        }
    }

HTH Someone

Sam

sambomartin