MVVM – Using ContentTemplateSelector in Tab Control View
August 19, 2013 Leave a comment
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
- Countries Tab, and
- 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