2
votes

If I have a class called: GuiObject, and that class has a list of GuiObjects called: "GuiObjects".

Now say my window has a list of GuiObjects, which I use in the .xaml file to dataBind to:

<StackPanel>
    <ItemsControl ItemsSource="{Binding TopObjectList}" DataTemplateSelector="{DynamicResource templateSelector"/> 
</StackPanel>

I can make a datatemplate for every type of FrameworkElement I want to generate, but I'm having trouble with the TabControl. I can create a datatemplate for the tabControl like so:

<DataTemplate x:key="TabControlTemplate" DataTemplateSelector="{DynamicResource templateSelector" >
    <TabControl ItemsSource="{Binding GuiObjects}" />
</DataTemplate>

And the result is a tab control that has each of the proper pages present, but without the contents of the individual TabItems. Fair enough, I'll just make a DataTemplate for the TabItems. For each TabItem, I'd like to put the contents of GuiObjects into a stackpanel.

<DataTemplate x:key="TabItemTemplate" DataTemplateSelector="{Resource templateSelector">
    <TabItem Header = {Binding Title}>
        <StackPanel>
            <ItemsControl ItemsSource="{Binding GuiObjects}" DataTemplateSelector="{DynamicResource templateSelector"/> 
        </StackPanel>
    </TabItem>
</DataTemplate>

The problem here is that the TabItemTemplate never gets called. I've tried solutions that involve setting the ItemContainerStyle within the TabControlTemplate, but then I've got the problem of hierarchy. If I bind "GuiObjects" inside the content of the TabItem, I'm binding the list of tabItems, instead of the list that's within each TabItem. (I want to do the second one). Here's an example:

<DataTemplate x:key="TabControlTemplate" DataTemplateSelector="{DynamicResource templateSelector" >
    <TabControl ItemsSource="{Binding GuiObjects}">
        <TabControl.ItemContainerStyle>
            <Style TargetType="TabItem">
                <Setter Property="Header" Value="{Binding Title}"/>
                <Setter Property="Content" Value="<StackPanel><ItemsControl ItemsSource="{Binding GuiObjects}" DataTemplateSelector="{DynamicResource templateSelector"/></StackPanel>"/>
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
</DataTemplate>

Again, this solution has the levels problem: When I say: {Binding GuiObjets} I'm referring to the list of TabItems, instead of to the list of FrameworkElements within each TabItem.

The solution is either to stick with separate DataTemplates for both the TabControl and the TabItem, and just fix it so that the DataTemplateSelector actually works for the TabItems (no idea how to do this). Or to go with the ItemContainerStyle, and somehow tell it to go down one level when binding GuiObjects. Anyone know how to do this?

1
DataTemplate does not have a DataTemplateSelector property, so I wonder how you can assign a value to one in your second code sample.O. R. Mapper

1 Answers

12
votes

To provide a template for the contents of the pages of a TabControl, use the following properties:

The ItemTemplate/ItemTemplateSelector properties of a TabControl are used to define what the tab headers look like.