MVVM – Using ContentTemplateSelector in Tab Control View

Requirement

I have a WPF TabView Control and Two Tab Items each containing different Tab Item Contents . I need to express this using MVVM / Binding.

ContentTemplateSelector is the place to go.

In the demo, we would have one TabView with two Tabs, they are

    1. Countries Tab, and
    2. Continents Tab.

Download Sample Project here: https://app.box.com/s/3rtqxpuj6x5eamj0wqrv

Steps

1. Create two Views (user Control) i.e. CountryView.xaml and ContinentsView.xaml, one for each tab item content.
2. Create a ViewModel for the Tab Control, here Tabs represent the TabItem’s

public class MyTabControlViewModel
    {
        public List<MyTabItemModel> Tabs { get; set; }
    }

3.  Create TabItemModel Class

public class MyTabItemModel
    {
        /// <summary>
        /// Tab Header text
        /// </summary>
        public string Header { get; set; }

        /// <summary>
        /// Tab Content 
        /// </summary>
        public IMyTabContentViewModel CurrentMyTabContentViewModel { get; set; }
}

4 .Create the Content Interface and implement the Content Views

public interface IMyTabContentViewModel
    {
    }
    public class CountryTabContentViewModel : IMyTabContentViewModel
    {
    }
    public class ContinentTabContentViewModel : IMyTabContentViewModel
    {
    }

5. Define two Data Templates, one for “Country view ” and another for “Continents view

<DataTemplate x:Key="CountryContentTemplate">
  <View1:CountryView DataContext="{Binding CurrentMyTabContentViewModel}"/>
        </DataTemplate>

<DataTemplate x:Key="ContinentsContentTemplate">
            <View1:ContinentsView DataContext="{Binding CurrentMyTabContentViewModel}"/>
</DataTemplate>

6. Create a Selector Class derived from DataTemplateSelector:

public class MyViewSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (((MyTabItemModel)(item)).CurrentMyTabContentViewModel is CountryTabContentViewModel)
            {
                return CountryTemplate;
            }
            return ContintentsTemplate;
        }
        public DataTemplate CountryTemplate {get;set;}

        public DataTemplate ContintentsTemplate{get;set;}
   }

7. Assign the DataTemplates to the appropriate Selector properties

<ViewModel:MyViewSelector x:Key="selector" 
    CountryTemplate="{StaticResource CountryContentTemplate}"
    ContintentsTemplate="{StaticResource ContinentsContentTemplate}" />

8. Map the ContentTemplateSelector property to the Selector. Your TabControl would look like this :

<UserControl x:Class=”TabControlItemTemplateDemo.View.MyTabControl”
             xmlns:ViewModel=”clr-namespace:TabControlItemTemplateDemo”
             xmlns:View1=”clr-namespace:TabControlItemTemplateDemo.View” mc:Ignorable=”d”
             d:DesignHeight=”300″ d:DesignWidth=”300″>
    <UserControl.Resources>
        <DataTemplate x:Key=”MyTabHeaderTemplate”>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=”*” />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column=”0″ Text=”{Binding Header}” Width=”80″ Height=”25″ FontWeight=”Bold”/>
            </Grid>
        </DataTemplate>
        <DataTemplate x:Key=”CountryContentTemplate”>
            <View1:CountryView DataContext=”{Binding CurrentMyTabContentViewModel}”/>
        </DataTemplate>
        <DataTemplate x:Key=”ContinentsContentTemplate”>
            <View1:ContinentsView DataContext=”{Binding CurrentMyTabContentViewModel}”/>
        </DataTemplate>
        <ViewModel:MyViewSelector x:Key=”selector”
                                           CountryTemplate=”{StaticResource CountryContentTemplate}”
                                           ContintentsTemplate=”{StaticResource ContinentsContentTemplate}” />
    </UserControl.Resources>
    <DockPanel>
        <TabControl ItemsSource=”{Binding Tabs}” TabStripPlacement=”Left”
                    BorderThickness=”0″ Background=”White”
                    ItemTemplate=”{StaticResource MyTabHeaderTemplate}”
                    ContentTemplateSelector=”{StaticResource selector}”>
        </TabControl>
    </DockPanel>
</UserControl>

Download Sample Project here: https://app.box.com/s/3rtqxpuj6x5eamj0wqrv