2

I have a collection of ViewModels I want to bind to the ItemsSource property of a TabControl and be able to add/remove them dynamically, so have implemented as an Observable<TabViewModel>.

However the TabControl seems to expect types which inherit from TabItem, which is a visual control object. I don't want my ViewModels to inherit from TabItem as that means they then need to be bound to a visual implementation and also all tests need to run as STA.

How can I bind a collection of ViewModels to populate the headers and content of a tab control without depending on the TabItem object? Ie just using styles and templates I suppose based on the ViewModel type. Just like if you had a ListBox and wanted the items to render directly from viewmodel instances, with a specific template, that is easy to do by overriding the ItemTemplate property.

How do I do this with a TabControl without using TabItem?

mm8
  • 163,881
  • 10
  • 57
  • 88
NZJames
  • 4,963
  • 15
  • 50
  • 100
  • So you want to create TabItems based on a collection ? – Nawed Nabi Zada May 15 '18 at 13:51
  • Not sure if this is quite what you're looking for but this was a [great video](https://www.youtube.com/watch?v=rFhmTccRUpQ) that I used when I started working with the TabControl. – Sudsy1002 May 15 '18 at 13:52
  • https://stackoverflow.com/a/5651542/1228 I just looked up this answer. Weird. –  May 15 '18 at 18:35

1 Answers1

2

How can I bind a collection of ViewModels to populate the headers and content of a tab control without depending on the TabItem object?

Try this:

View:

<TabControl ItemsSource="{Binding Items}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Header}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Content}" />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

View Model:

public class TabViewModel
{
    public TabViewModel()
    {
        Items = new ObservableCollection<Item>()
        {
            new Item { Header = "a", Content = "..." },
            new Item { Header = "b", Content = "..." },
            new Item { Header = "c", Content = "..." },
        };
    }

    public ObservableCollection<Item> Items { get; set; }
}

Item is a POCO class.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • Great, did the trick. Just one thing I forgot to mention in my question. My content items are ViewModels themselves, each with a template that dictates how to render it. I have used the ItemContainerStyle to set the template for the header fine, but cannot figure out how to set the content style. Do you know how to do this? – NZJames May 15 '18 at 14:17
  • @NZJames: Please see my answer here: https://stackoverflow.com/questions/50353014/tabcontrol-not-finding-data-templates-for-tabcontrol-items – mm8 May 15 '18 at 14:51