Binding TabControl ItemsSource to Collection of ViewModels
I ended up using a ContentControl
with a TabControl
data template (like the original tutorial project). Here is the xaml code I ended up with. I did not change the code-behind from the original sample project to make this work. The ContentControl
is in my MainWindow.xaml and the other two pieces of code were in a ResourceDictionary
.
<!-- Workspaces Tab Control -->
<ContentControl Grid.Row="1"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}"/>
<!-- Workspaces Template -->
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl Style="{StaticResource ClosableTabControl}"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource WorkspaceTabItemTemplate}"
Margin="1"/>
</DataTemplate>
<!-- Workspace Tab Item Template -->
<DataTemplate x:Key="WorkspaceTabItemTemplate">
<Grid Width="Auto" Height="Auto">
<ContentPresenter ContentSource="Header" Margin="3"
Content="{Binding Path=DisplayName}"
HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Foreground}"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</DataTemplate>
akagixxer
Updated on July 26, 2022Comments
-
akagixxer almost 2 years
For some reason I am having a heck of a time getting my
TabControl
to display properly when binding theItemsSource
to aObservableCollection
of view models. I'm basing my design off of the tutorial found here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx. I did find a few questions like mine here but none addressed my particular situation. This is myTabControl
in xaml.<TabControl ItemsSource="{Binding Workspaces}" SelectedIndex="{Binding ActiveWorkspaceIndex}" ItemTemplate="{StaticResource ClosableTabItemTemplate}"/>
Where
ClosableTabItemTemplate
is the following.<DataTemplate x:Key="ClosableTabItemTemplate"> <DockPanel Width="120"> <Button Command="{Binding Path=CloseCommand}" Content="X" Cursor="Hand" DockPanel.Dock="Right" Focusable="False" FontFamily="Courier" FontSize="9" FontWeight="Bold" Margin="0,1,0,0" Padding="0" VerticalContentAlignment="Bottom" Width="16" Height="16" /> <ContentPresenter Content="{Binding Path=DisplayName}" VerticalAlignment="Center" /> </DockPanel> </DataTemplate>
Workspaces
is theObservableCollection
of view models.ActiveWorkspaceIndex
is just the active workspace index that I keep track of in the view model. I associate my view model with an instance of a view through the following data template in my App.xaml file.<DataTemplate DataType="{x:Type vm:ViewModelStartPage}"> <v:ViewStartPage/> </DataTemplate>
I only add one view model to my collection of workspaces. I see 2 views display in the tab control and they aren't tabbed. It's almost like the TabControl doesnt know to treat the different views as TabItems, its behaving more like a stack panel, stacking the views. If I create the tab items in code it works fine like this:
System.Windows.Controls.TabItem i = new System.Windows.Controls.TabItem(); i.Content = new Views.ViewStartPage(); i.Header = "A Tab Item"; this.xTabControl.Items.Add(i);
I must be missing some content template or something. I will be styling my tabs later but for now I would be happy just getting the basic tabs working. Also the views in the tab contents may be different for each tab so I can't use the simple textblock TabControl template examples I see all over the place... I.e. not this...
<TabControl.ContentTemplate> <DataTemplate> <TextBlock Text="{Binding Content}" /> </DataTemplate>
Any ideas?