TabItems from View collection
I am using MVVM. I have a tab control. I will have a collection of items. I want to display each of this item in the collection as a tab item. The view in each tab item is different and may have its own viewmodel. How do I achieve this? E.g. I have 3 items in the collection. The Tab item template contains an ItemControl. I would like to now have 3 Tabs created and the ItemControls inside each tabitem may be showing different views.
One way I could do is have a single view and viewmodel for each item. Now based on some condition the View will display different UI elements and behave differently. But I am afraid thi开发者_开发技巧s will make the view quite complex over a period of time.
Edit: Goblin's solution below works fine but I have an issue when a custom style applied to TabControl.
<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" Name="RowDefinition0" />
<RowDefinition Height="*" Name="RowDefinition1" />
</Grid.RowDefinitions>
<TabPanel Grid.Column="0" Grid.Row="0" />
<Border Grid.Column="0" Grid.Row="1">
<ContentPresenter Content="{TemplateBinding TabControl.SelectedContent}" ContentTemplate="{TemplateBinding TabControl.SelectedContentTemplate}" ContentStringFormat="{TemplateBinding TabControl.SelectedContentStringFormat}" ContentSource="SelectedContent" Name="PART_SelectedContentHost" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
EDIT: This has been resolved by adding ContentTemplateSelector to the ContentPresenter in the above TabControl style
Create a datatemplate for each view. Implement a DataTemplateSelector class which given an item returns the correct datatemplate. If the collection of items is called Items your xaml would look something like this
<TabControl
ItemsSource="{Binding Path=Items}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}" />
Have you tried using DataTemplateSelectors?
Basically, you publish a collection of smaller ViewModels in your main ViewModel - then in the DataTemplateSelector choose your template based on the type of ViewModel?
<UserControl.Resources>
<DataTemplate x:Key="HeaderTemplate">
<TextBlock Text="CMR"/>
</DataTemplate>
<DataTemplate x:Key="FirstTemplate">
<local:FirstView/>
</DataTemplate>
<DataTemplate x:Key="SecondTemplate">
<lcoal:SecondView/>
</DataTemplate>
<local:TemplateSelector x:Key="TemplateSelector" FirstTypeTemplate="{StaticResource FirstTemplate}" SecondTypeTemplate={StaticResource SecondTemplate}/>
</UserControl.Resources>
<TabControl ItemsSource="{Binding SmallerViewModels}" ContentTemplateSelector="{StaticResource TemplateSelector}" ItemTemplate="{StaticResource HeaderTemplate}">
In Code-behind:
public class TemplateSelector:DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if(item.GetType() == typeof(FirstViewModel)
return FirstTypeTemplate
return SecondTypeTemplate;
}
public DataTemplate FirstTypeTemplate { get; set; }
public DataTemplate SecondTypeTemplate { get; set; }
}
EDIT: ViewModels:
public class SharedViewModel
{
public SharedViewModel()
{
SmallerViewModels = new List<ISmallViewModel>();
SmallerViewModels.Add(new FirstViewModel());
SmallerViewModels.Add(new SecondViewModel());
}
public IList<ISmallViewModel> SmallerViewModels{get;private set;}
}
public interface ISmallViewModel{}
public class FirstViewModel:ISmallViewModel
{
public string FirstDescription
{
get{return "My first ViewModel";}
}
}
public class SecondViewModel:ISmallViewModel
{
public string SecondDescription
{
get{return "My second ViewModel";}
}
}
Views
<UserControl .... x:Class="...FirstView">
<TextBlock Text="{Binding FirstDescription}"
</UserControl>
<UserControl .... x:Class="...SecondView">
<TextBlock Text="{Binding SecondDescription}"
</UserControl>
精彩评论