Coder323
Coder323

Reputation: 580

MVVM for tabcontrol based application

In my wpf application the main view has 5 tabs with 5 different usercontrols , since the user controls are not related to each other, I have created 5 different view models (apart from the main viewmodel).

I thought of having a List or dictionary to have the list of usercontrols and its viewmodels, Now, I would like to bind the tabitems with the list of usercontrols and assign the datacontexts, but since the list or dictionary can be changed, I dont find a way to bind the usercontrols to the tabitems.

For example, If I have a single tab which will be associated with a usercontrol I can assign

 tab1View tview=new tab1View();
 tview.DataContext= new tab1ViewModel();
 tab1.Content=tview;

But how can I do the same from a list which has the reference of the view and viewmodels of the usercontrols?

Please teach me a best way to achieve this.

**Answer: **

I got the answer for what I need. First, Generic type collection of the view models should be created C# - Multiple generic types in one list

public abstract class Metadata
{
}

public class Metadata<DataType> : MetaData where DataType : class
{
private DataType mDataType;
}
List<Metadata> metadataObjects;
metadataObjects.Add(new Metadata<tab1ViewModel>());
metadataObjects.Add(new Metadata<tab2ViewModel>());

Then create a DataTemplate selector if multiple views are to be be referenced with same viewmodel or just apply the DataTemplate

Upvotes: 1

Views: 2954

Answers (2)

myermian
myermian

Reputation: 32515

There are a few ways to handle this, though I'd look at using frameworks to help you with MVVM. I myself promote Prism.

View Injection


View Discovery


DataTemplates - Sample

With DataTemplates you're defining in XAML (or in code, but XAML is more likely) which view to "automagically" apply to a ContentControl based upon the view-model (DataContext).

Somewhere in the XAML resources:

<DataTemplate DataType="{x:Type ViewModel:GeneralSettingsViewModel}">
    <View:GeneralSettingsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:AdvancedSettingsViewModel}">
    <View:AdvancedSettingsView/>
</DataTemplate>

Somewhere in the XAML file that has the resources applied to it:

 <TabControl ItemsSource="{Binding MyViewModelCollection}" />

Note: This only works if you have one view-model per DataTemplate in the scoped resource.


DataTemplateSelector

If you have a view-model that can be applied to multiple views and you determine those views through additional logic, you would want to use a DataTemplateSelector. Here is an example:

Somewhere in the XAML resources:

<!-- Possible collision because the DataType is of the same type -->
<DataTemplate x:Key="GeneralSettingsTemplate"
              DataType="{x:Type ViewModel:SettingsViewModel}">
    <View:GeneralSettingsView/>
</DataTemplate>
<DataTemplate x:Key="AdvancedSettingsTemplate"
              DataType="{x:Type ViewModel:SettingsViewModel}">
    <View:AdvancedSettingsView/>
</DataTemplate>
<local:SettingsDataTemplateSelector x:Key="SettingsTemplateSelector"
    GeneralSettingsTemplate="{StaticResource GeneralSettingsTemplate}"
    AdvancedSettingsTemplate="{StaticResource AdvancedSettingsTemplate}" />

Somewhere in the XAML file that has the resources applied to it:

<TabControl ItemsSource="{Binding MyViewModelCollection}"
            ItemTemplateSelector="{StaticResource SettingsTemplateSelector}" />

SettingsTemplateSelector.cs:

public class SettingsDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate GeneralSettingsTemplate { get; set; }
    public DataTemplate AdvancedSettingsTemplate { get; set; }

    public override DataTemplate SelectTemplate(Object item,
        DependencyObject container)
    {
        var vm = item as SettingsViewModel;

        if (vm == null) return base.SelectTemplate(item, container);

        if (vm.IsAdvanced)
        {
            return AdvancedSettingsTemplate;
        }

        return GeneralSettingsTemplate;
    }
}

MSDN: Prism Navigation - http://msdn.microsoft.com/en-us/library/gg430861(v=PandP.40).aspx
This covers Prism Regions as well as other parts of navigation.

MSND: View Discovery vs View Injection - http://msdn.microsoft.com/en-us/library/ff921075(v=pandp.20).aspx
This section covers the differences of View Discovery and View Injection and when to use each.

Upvotes: 5

cordialgerm
cordialgerm

Reputation: 8503

Create a collection of your viewmodels that you bind to the ItemsSource of the tab control. Then create a DataTemplateSelector to select a view for each viewmodel.

Upvotes: 2

Related Questions