BatteryBackupUnit
BatteryBackupUnit

Reputation: 13233

Binding TabControl.ItemsSource to ViewModels whose View's are a TabItem

I need some TabItems to have a customized Header. For example, given the following (working) XAML:

<TabControl>
    <TabItem>
        <TabItem.Header>
            <Button>Header 1</Button>
        </TabItem.Header>
        <Label>Content 1</Label>
    </TabItem>

    <TabItem>
        <TabItem.Header>
            <Label>Header 2</Label>
        </TabItem.Header>
        <Grid>
            <TextBlock>Content 2</TextBlock>
        </Grid>
    </TabItem>
</TabControl>

I would like to extract the tab items into their own Views + ViewModels. The TabItem's View should still be a TabItem, so that I can configure the Header per tab item instead of setting TabControl.ItemTemplate and using a DataTemplateSelector to achieve different headers per tab item.

At the same time I'd need to be able to bind the selected tab item view model to a property ActiveItem. => The underlying view-model for the TabControl is a Conductor.Collection.OneActive<T> (only the selected tab should be activated).

If there's an alternative to using TabItem as view-type, but still achieving the Header and Content to be specified in the same view, it would be acceptable, too.

Upvotes: 0

Views: 889

Answers (1)

Kcvin
Kcvin

Reputation: 5163

You should be able to achieve this by binding a TabControlViewModel to the TabControl, and that VM should have an ObservableCollection of TabViewModels (maybe a base class or interface). You would bind your collection of TabViewModels to the TabControl's ItemsSource. Here is my implementation, but using the Telerik TabControl (should be same for MS):

<telerik:RadTabControl x:Name="RadTabControl"
                        Grid.Row="0"
                        Align="Justify"
                        ContentTemplateSelector="{StaticResource LoggerDataTemplateSelector}"
                        IsContentPreserved="True"
                        IsDefaultItemSelected="True"
                        ItemsSource="{Binding LogHistory}"
                        SupressSelectedContentTemplateReapplying="False">
    <telerik:RadTabControl.ItemContainerStyle>
        <!-- Allow IsSelected to be bound to view models-->
        <Style BasedOn="{StaticResource RadTabItemStyle}"
                TargetType="{x:Type telerik:RadTabItem}">
            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
        </Style>
    </telerik:RadTabControl.ItemContainerStyle>
    <telerik:RadTabControl.ItemTemplate>
        <!-- Define what is shown in the header -->
        <DataTemplate>
            <Grid Height="30">
                <TextBlock VerticalAlignment="Center"
                            Text="{Binding Title}" />
            </Grid>
        </DataTemplate>
    </telerik:RadTabControl.ItemTemplate>
</telerik:RadTabControl>

Be aware, MS doesn't have something like IsContentPreserved, so switching tabs that have a lot of data to show will be rather timely. There are also a couple other properties not in MS TabControl, however the important properties should all be there. In this case, your TabViewModel should have a IsSelected property and Title property.

Upvotes: 2

Related Questions