Reputation: 580
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
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.
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
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