Noich
Noich

Reputation: 15501

WPF: binding several views to a TabControl's items

In the current project we work on, we have a main window with several views (each with its own viewmodel) that are presented as items in a tab control. E.g: One tab item is an editor, and contains the editor view as follows:

<TabItem Header="Test Editor">
            <TestEditor:TestEditorView DataContext="{Binding TestEditorViewModel}"/>
</TabItem>

Another one shows results:

<TabItem Header="Results Viewer">
     <ResultViewer:ResultViewer x:Name="resultViewer1" DataContext="{Binding Path=ResultViewModel}"  />
</TabItem>

etc.
I'd like to have the TabItems bound to something in the main window's viewmodel, but I can't figure out how to bind the view's name to any property without breaking the MVVM pattern. I'd like to have something like:

 <TabControl.ContentTemplate>
     <DataTemplate>
         <TestEditor:TestEditorView DataContext ="{Binding TabDataContext}"/>
     </DataTemplate>
 </TabControl.ContentTemplate>

only with some binding instead of having to know at design time what type will be used as content.
Any ideas?

Upvotes: 2

Views: 5817

Answers (1)

Rachel
Rachel

Reputation: 132648

Usually I have the TabControl's Tabs stored in the ViewModel, along with the SelectedIndex, then I use DataTemplates to determine which View to display

View:

<Window>
    <Window.Resources>
        <DataTemplate DataType="{x:Type ResultViewModel}">
            <ResultViewer:ResultViewer />
        </DataTemplate>
        <DataTemplate DataType="{x:Type EditorViewModel}">
            <TestEditor:TestEditorView />
        </DataTemplate>
    </Window.Resources>

    <TabControl ItemsSource="{Binding TabCollection}"
                SelectedIndex="{Binding SelectedTabIndex}" />

</Window>

ViewModel:

public class MyViewModel : ViewModelBase
{

    publicMyViewModel()
    {
        TabCollection.Add(new ResultsViewModel());
        TabCollection.Add(new EditorViewModel());
        SelectedTabIndex = 0;
    }

    private ObservableCollection<ViewModelBase> _tabCollection
        = new ObservableCollection<ViewModelBase>();

    public ObservableCollection<ViewModelBase> TabCollection
    {
        get { return _tabCollection };
    }

    private int _selectedTabIndex;
    public int SelectedTabIndex
    {
        get { return _selectedTabIndex; }
        set
        {
            if (value != _selectedTabIndex)
            {
                _selectedTabIndex = value;
                RaisePropertyChanged("SelectedTabIndex");
            }
        }
    }
}

Upvotes: 5

Related Questions