Multiple view models with MahApps.Metro within TabControl

524 views Asked by At

I'm trying to get a TabControl to displays holding data from two different categories/viewmodels. Based on these two resources, WPF MahApps.Metro Tabcontrol data bound? and DataTemplates aren't applied, I tried the following which doesn't quite make the cut as it gives an compilation error.

<TabControl ItemsSource="{Binding Collection}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Title}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate DataType="{x:Type viewModels:SubViewModelAlpha}">
            <TextBlock>SubViewModelAlpha</TextBlock>
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewModels:SubViewModelBeta}">
            <TextBlock>SubViewModelBeta</TextBlock>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

I have the corresponding classes:

public class ViewModel { 
   public string Title { get; set; }
}

public class SubViewModelAlpha : ViewModel { }
public class SubViewModelBeta : ViewModel { }

// In another class, I have this property ... 
public ObservableColletion<ViewModel> Collection {
   get { return _collection; } 
}
// ... and this list
private ObservableColletion<ViewModel> _collection;

The error I get is "Property ContentTemplate is set more than once", which kind of make sense, but how can I apply the same type of checking against a type of ViewModel before setting the ContentTemplate stuff?

I have already tried using the DataType on the ContentTemplate but that doesn't work.

PS! I do of course want much more data within each viewmodel, but this example shows the gist of what I'm trying to achieve.

2

There are 2 answers

0
holroy On BEST ANSWER

After reading some more, it seems like the issue can be solved using a ContentTemplateSelector, albeit I'm not sure if there are any strange dependcies going on.

I changed my xaml to look like:

<TabControl ItemsSource="{Binding Collection}"
            ContentTemplateSelector="{DynamicResource MyContentTemplateSelector}">
    <TabControl.Resource>
        <DataTemplate x:Key="BetaTemplate" DataType="{x:Type viewModels:SubViewModelAlpha}">
            <TextBlock>SubViewModelAlpha</TextBlock>
        </DataTemplate>
        <DataTemplate x:Key="BetaTemplate" DataType="{x:Type viewModels:SubViewModelBeta}">
            <TextBlock>SubViewModelBeta</TextBlock>
        </DataTemplate>
        <viewModels:MyContentTemplateSelector
            x:Key="MyContentTemplateSelector" 
            AlphaTemplate="{StaticResource AlphaTemplate}"
            BetaTemplate="{StaticResource BetaTemplate}" />
    <TabControl.Resource>
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Title}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

With the following class added to my project:

public class MyContentTemplateSelector : DataTemplateSelector
{
    public DataTemplate AlphaTemplate { get; set; }
    public DataTemplate BetaTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is SubViewModelAlpha) 
            return AlphaTemplate;

        if (item is SubViewModelBeta)
            return BetaTemplate;

        return base.SelectTemplate(item, container);
    }
}

This code is loosely based on Using ContentTemplateSelector, and I'm not sure what kind of caveats there are, if any.

I do however believe an even nicer solution directly using the data type is availabe, but I don't know how! Yet...

5
Ahmed Fwela On

the problem here i think is that the content template it self doesn't accept more than a single template , it's like when you add two grids for a single window it will tell you that the content property can't be set more than once

what i can think of here from a basic prospective is that you can do a single template that combines both template and choose between them by triggers and converters

Edit

check this article http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector