Load UserControl in TabItem

PitAttack76 picture PitAttack76 · Mar 20, 2012 · Viewed 25.7k times · Source

I have a Usercontrol(TabUserControl) which contains a TabControl. The Viewmodel of that UserControl loads ab Observable collection of TabItems. One od those items is another user control. When I just load text in the tabcontrol there is no problem, but how can I load the other user control into the tabitem of the TabUserControl. I'm using MVVM.

Here's my code:

public class TabItem
{
    public string Header { get; set; }
    public object Content { get; set; } // object to allow all sort of items??
}

The Viewmodel of the TabUserControl

public class TabViewModel
{
    public ObservableCollection<TabItem> Tabs {get;set;}

    public TabViewModel()
    {
        Tabs = new ObservableCollection<TabItem>();
        //Tabs.Add(new TabItem { Header = "Overview", Content = new OverviewViewModel() }); How to load a usercontrol here if it's in the ItemCollection?
        Tabs.Add(new TabItem { Header = "Overview", Content = "Bla bla bla" });
        Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
    }
}

And then the TabControl XAML:

<TabControl x:Name="_tabControl"
            ItemsSource="{Binding Tabs}">
  <TabControl.ItemContainerStyle>
    <Style TargetType="TabItem">
      <Setter Property="Header"
              Value="{Binding Header}" />
      <Setter Property="Content"
              Value="{Binding Content}" />
    </Style>
  </TabControl.ItemContainerStyle>
</TabControl>

It works as long as I dont load the viewmodel of the usercontrol in the tabItems collection. how can I make the UserTabControl load on to the TabItem? The intention is that every tabitem will contain a usercontrol. Each usercontrol then does it's own thing.

Hope someone can help me as I am a WPF beginner. Thx!

Answer

Rachel picture Rachel · Mar 21, 2012

Ideally, the TabControl.ItemsSource should be set to a collection of ViewModels, and DataTemplates should be used to tell the WPF to draw each ViewModel with a specific UserControl.

This keeps between your business logic (ViewModels) completely separate from your UI (Views)

For example,

<TabControl x:Name="MyTabControl"
            ItemsSource="{Binding TabViewModels}"
            SelectedItem="{Binding SelectedTabViewModel}">

    <TabControl.Resources>
        <DataTemplate DataType="{x:Type my:ViewModelA}">
            <my:ViewAUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:ViewModelB}">
            <my:ViewBUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:ViewModelC}">
            <my:ViewCUserControl />
        </DataTemplate>
    </TabControl.Resources>

    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="Header" Value="{Binding Header}" />
        </Style>
    </TabControl.ItemContainerStyle>

</TabControl>

ViewModel containing TabControl's DataContext:

TabViewModels = new ObservableCollection<ITabViewModel>();
TabViewModels.Add(new ViewModelA { Header = "Tab A" });
TabViewModels.Add(new ViewModelB { Header = "Tab B" });
TabViewModels.Add(new ViewModelC { Header = "Tab C" });

SelectedTabViewModel = TabViewModels[0];