Binding TabControl ItemsSource to Collection of ViewModels

10,901

I ended up using a ContentControl with a TabControl data template (like the original tutorial project). Here is the xaml code I ended up with. I did not change the code-behind from the original sample project to make this work. The ContentControl is in my MainWindow.xaml and the other two pieces of code were in a ResourceDictionary.

<!-- Workspaces Tab Control -->
      <ContentControl Grid.Row="1"
                      VerticalAlignment="Stretch"
                      HorizontalAlignment="Stretch"
                      Content="{Binding Path=Workspaces}"
                      ContentTemplate="{StaticResource WorkspacesTemplate}"/>

<!-- Workspaces Template -->
  <DataTemplate x:Key="WorkspacesTemplate">
    <TabControl Style="{StaticResource ClosableTabControl}"
                IsSynchronizedWithCurrentItem="True"
                ItemsSource="{Binding}"
                ItemTemplate="{StaticResource WorkspaceTabItemTemplate}"
                Margin="1"/>
  </DataTemplate>


<!-- Workspace Tab Item Template -->
  <DataTemplate x:Key="WorkspaceTabItemTemplate">
    <Grid Width="Auto" Height="Auto">
      <ContentPresenter ContentSource="Header" Margin="3" 
                        Content="{Binding Path=DisplayName}"
                        HorizontalAlignment="Center" VerticalAlignment="Center">
        <ContentPresenter.Resources>
          <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="{StaticResource Foreground}"/>
          </Style>
        </ContentPresenter.Resources>
      </ContentPresenter>
    </Grid>
  </DataTemplate>
Share:
10,901
akagixxer
Author by

akagixxer

Updated on July 26, 2022

Comments

  • akagixxer
    akagixxer almost 2 years

    For some reason I am having a heck of a time getting my TabControl to display properly when binding the ItemsSource to a ObservableCollection of view models. I'm basing my design off of the tutorial found here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx. I did find a few questions like mine here but none addressed my particular situation. This is my TabControl in xaml.

    <TabControl ItemsSource="{Binding Workspaces}"
                SelectedIndex="{Binding ActiveWorkspaceIndex}"
                ItemTemplate="{StaticResource ClosableTabItemTemplate}"/>
    

    Where ClosableTabItemTemplate is the following.

    <DataTemplate x:Key="ClosableTabItemTemplate">
            <DockPanel Width="120">
              <Button 
                  Command="{Binding Path=CloseCommand}"
                  Content="X"
                  Cursor="Hand"
                  DockPanel.Dock="Right"
                  Focusable="False"
                  FontFamily="Courier" 
                  FontSize="9"
                  FontWeight="Bold"  
                  Margin="0,1,0,0"
                  Padding="0"
                  VerticalContentAlignment="Bottom"
                  Width="16" Height="16" 
                  />
              <ContentPresenter 
                  Content="{Binding Path=DisplayName}" 
                  VerticalAlignment="Center" 
                  />
            </DockPanel>
          </DataTemplate>
    

    Workspaces is the ObservableCollection of view models. ActiveWorkspaceIndex is just the active workspace index that I keep track of in the view model. I associate my view model with an instance of a view through the following data template in my App.xaml file.

    <DataTemplate DataType="{x:Type vm:ViewModelStartPage}">
         <v:ViewStartPage/>
     </DataTemplate>
    

    I only add one view model to my collection of workspaces. I see 2 views display in the tab control and they aren't tabbed. It's almost like the TabControl doesnt know to treat the different views as TabItems, its behaving more like a stack panel, stacking the views. If I create the tab items in code it works fine like this:

    System.Windows.Controls.TabItem i = new System.Windows.Controls.TabItem();
    i.Content = new Views.ViewStartPage();
    i.Header = "A Tab Item";
    this.xTabControl.Items.Add(i); 
    

    I must be missing some content template or something. I will be styling my tabs later but for now I would be happy just getting the basic tabs working. Also the views in the tab contents may be different for each tab so I can't use the simple textblock TabControl template examples I see all over the place... I.e. not this...

    <TabControl.ContentTemplate>
        <DataTemplate>
            <TextBlock
               Text="{Binding Content}" />
        </DataTemplate>
    

    Any ideas?