title: bind different modelview and view to each TabItem via MVVM in WPF
body: <p>I'm using MVVM to dynamically create tabs from viewModel.
  In code, my attempt is to hold collection of "TabItem" that specify how tab appears (custom template) &amp; in addition ModelView object, and then based on modelview display on the TabItem view #1 / or view #2. </p>
  
  <p>My current s/w architecture is as follows:</p>
  
  <p>My MainWindow.xaml:</p>
  
  <pre><code>&lt;Window
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:ViewModel="clr-namespace:MyApp.ViewModel" x:Class="MyApp.MainWindow"
      xmlns:Views="clr-namespace:MyApp.View"
      Height="700" Width="1000" Background="#FF1B0000" ResizeMode="NoResize"&gt;
  
  &lt;Window.DataContext&gt;
      &lt;ViewModel:TabItemViewModel/&gt;
  &lt;/Window.DataContext&gt;
  &lt;Grid&gt;
  
      &lt;TabControl Background="Black" Margin="0,25,0,0" BorderThickness="0,0,0,0" ItemsSource="{Binding Tabs}" BorderBrush="Black" &gt;
  
              &lt;TabControl.ItemTemplate&gt;
                  &lt;!-- this is the header template--&gt;
                  &lt;DataTemplate&gt;
                      &lt;Grid Margin="0"&gt;
                          &lt;Border Margin="0,0,0,0" 
                              Background="Black"
                              BorderBrush="Black" 
                              BorderThickness="0,0,0,0" Padding="0,0,0,0"&gt;
                              &lt;StackPanel   Orientation="Horizontal"
                                          Margin="0,0,0,0"&gt;
                                  &lt;Image Name ="tabImage" Source="{Binding TabImage_Disabled}" /&gt;
                              &lt;/StackPanel&gt;
                          &lt;/Border&gt;
                      &lt;/Grid&gt;
                      &lt;DataTemplate.Triggers&gt;
                          &lt;DataTrigger Binding="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent}}" Value="True"&gt;
                              &lt;Setter TargetName="tabImage" Property="Source" Value="{Binding TabImage_Enabled}"/&gt;
                          &lt;/DataTrigger&gt;
                      &lt;/DataTemplate.Triggers&gt;
                  &lt;/DataTemplate&gt;
              &lt;/TabControl.ItemTemplate&gt;
              &lt;TabControl.ContentTemplate&gt;
                  &lt;!-- this is the body of the TabItem template--&gt;
                  &lt;DataTemplate&gt;
                      &lt;TextBlock Text="{Binding TabContents}" Foreground="white" /&gt;
                  &lt;/DataTemplate&gt;
              &lt;/TabControl.ContentTemplate&gt;
         &lt;/TabControl&gt;
  
  
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>TabItem.cs:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Windows;
  using System.Windows.Media.Imaging;
  using MyApp.ViewModel;
  
  namespace MyApp.Model
  {
      public sealed class TabItem
      {
          public string TabName { get; set; }
          public BitmapImage TabImage_Enabled { get; set; }
          public BitmapImage TabImage_Disabled { get; set; }
          public BitmapImage TabImage_Background { get; set; }
          public ViewModelBase TabContents { get; set; }
      }
  }
  </code></pre>
  
  <p>ViewModelBase.cs:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  
  namespace MyApp.ViewModel
  {
      public class ViewModelBase : INotifyPropertyChanged
      {
  
           public event PropertyChangedEventHandler PropertyChanged;
  
           protected virtual void RaisePropertyChanged(string propertyName)
           {
                var handler = this.PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
           }
      }
  }
  </code></pre>
  
  <p>TabItemViewModel.cs:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Collections.ObjectModel;
  using System.Linq;
  using System.Text;
  using System.Windows.Media.Imaging;
  using MyApp.Model;
  
  namespace MyApp.ViewModel
  {
  public sealed class TabItemViewModel : ViewModelBase
  {
  
      const int NUMBER_OF_TABS = 2;
  
      enum enum_Tabs
      {
          Research_Tab = 0,
          Engineering_Tab = 1
      }
  
      Uri[] _aUrisEnabled = new Uri[NUMBER_OF_TABS];
      Uri[] _aUrisDisabled = new Uri[NUMBER_OF_TABS];
      Uri[] _aUrisBackgroundPics = new Uri[NUMBER_OF_TABS];
      BitmapImage[] _aEnabledTabImages = new BitmapImage[NUMBER_OF_TABS];
      BitmapImage[] _aDisabledTabImages = new BitmapImage[NUMBER_OF_TABS];
      BitmapImage[] _aBackgroundTabImages = new BitmapImage[NUMBER_OF_TABS];
  
      private ObservableCollection&lt;TabItem&gt; _tabs;
  
      public ObservableCollection&lt;TabItem&gt; Tabs
      {
          get { return _tabs; }
          set
          {
              _tabs = value;
              RaisePropertyChanged("Tabs");
          }
      }
  
      public TabItemViewModel()
      {
          Tabs = new ObservableCollection&lt;TabItem&gt;();
  
  
          // URIs
  
          // enabled pics
          _aUrisEnabled[(int)enum_Tabs.Research_Tab] = new Uri("pack://application:,,,/Images/research_enabled.png");
          _aUrisEnabled[(int)enum_Tabs.Engineering_Tab] = new Uri("pack://application:,,,/Images/engineering_enabled.png");
  
          // disabled pics
          _aUrisDisabled[(int)enum_Tabs.Research_Tab] = new Uri("pack://application:,,,/Images/research_disabled.png");
          _aUrisDisabled[(int)enum_Tabs.Engineering_Tab] = new Uri("pack://application:,,,/Images/engineering_disabled.png");
  
          // Tab backgrounds
          _aUrisBackgroundPics[(int)enum_Tabs.Research_Tab] = new Uri("pack://application:,,,/Images/research_background.png");
          _aUrisBackgroundPics[(int)enum_Tabs.Engineering_Tab] = new Uri("pack://application:,,,/Images/engineering_background.png");
  
          // Load all images
          for (int iImageIndex = 0; iImageIndex &lt; NUMBER_OF_TABS; iImageIndex++)
          {
              _aEnabledTabImages[iImageIndex] = new BitmapImage(_aUrisEnabled[iImageIndex]);
              _aDisabledTabImages[iImageIndex] = new BitmapImage(_aUrisDisabled[iImageIndex]);
              _aBackgroundTabImages[iImageIndex] = new BitmapImage(_aUrisBackgroundPics[iImageIndex]);
          }
  
  
          Tabs.Add(new TabItem { TabName = "Research", TabImage_Enabled = _aEnabledTabImages[(int)enum_Tabs.Research_Tab], TabImage_Disabled = _aDisabledTabImages[(int)enum_Tabs.Research_Tab], TabImage_Background = _aBackgroundTabImages[(int)enum_Tabs.Research_Tab], TabContents = new TabResearchViewModel() });
          Tabs.Add(new TabItem { TabName = "Engineering", TabImage_Enabled = _aEnabledTabImages[(int)enum_Tabs.Engineering_Tab], TabImage_Disabled = _aDisabledTabImages[(int)enum_Tabs.Engineering_Tab], TabImage_Background = _aBackgroundTabImages[(int)enum_Tabs.Engineering_Tab], TabContents = new TabEngineeringViewModel() });
           }
  
       }
  }
  </code></pre>
  
  <p>My problem id how do i specify custom template (for TabHeader, since im showing picture instead of TextBlock) in addition to view. </p>
  
  <p>I've tried searching on google &amp; on this site, but couldn't find solution that use custom template.
  I've found some solution of TempleateSelector, but i'm unsure as to how combine it with MVVM.</p>
  
  <p>I've also attempted to write something like this in MainWIndow.xaml:</p>
  
  <pre><code>        &lt;TabControl Background="Black" Margin="0,25,0,0" BorderThickness="0,0,0,0"  ItemsSource="{Binding Tabs}" BorderBrush="Black" &gt;
  
              &lt;TabControl.Resources&gt;
                  &lt;DataTemplate DataType="{x:Type ViewModel:TabResearchViewModel}"&gt;
                      &lt;Views:TabResearchView /&gt;
                  &lt;/DataTemplate&gt;
                  &lt;DataTemplate DataType="{x:Type ViewModel:TabEngineeringViewModel}"&gt;
                      &lt;Views:TabEngineeringView /&gt;
                  &lt;/DataTemplate&gt;
              &lt;/TabControl.Resources&gt;
  
          ... (removed for clarity)
  </code></pre>
  
  <p>I want to replace the 
  <code>&lt;TextBlock Text="{Binding TabContents}" Foreground="white" /&gt;
            &lt;/DataTemplate&gt;</code>
  with something that will display "view" (page), while binding to the tabs collection...</p>
  
  <p>Would appreciate any help on matter.
  Thanks in advanced...</p>