I have a TabControl with a single specific tab and a collection bound to a collection of VMs, using a different user control. To do this I use a CompositeCollection and DataTemplates defined in the control's resources, selecting correct user control based on the VM type (acting as ContentTemplate).
I also set an ItemTemplate to define the tab item's name with binding, but it's not defined in the resource as I guess would conflict with the "ContentTemplate" ones.
It works fine, but I see the following error traced:
System.Windows.Data Error: 26 : ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='TabItem'
It looks like there's some conflict between ContentTemplate and ItemTemplate, but I don't know how to fix it?
Code is the following:
<TabControl HorizontalAlignment="Left" Height="300" Width="500">
<TabControl.Resources>
<CollectionViewSource x:Key="personCollection" Source="{Binding Persons}" />
<DataTemplate DataType="{x:Type viewModel:Main}">
<local:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:Person}">
<local:PersonView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemsSource>
<CompositeCollection>
<TabItem Header="General" Content="{Binding }"/>
<CollectionContainer Collection="{Binding Source={StaticResource personCollection}}" />
</CompositeCollection>
</TabControl.ItemsSource>
<TabControl.ItemTemplate>
<DataTemplate DataType="viewModel:Person">
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
The error you observe is pretty obvious.
You define the
ItemsSource
of yourTabControl
as aCompositeCollection
that contains elements of different types:TabItem
"General";Person
viewmodels.So you're just mixing in one collection a view and some viewmodels - that's not neat. WPF informs you about this with the error message. The engine tries to create views (using
DataTemplate
s) for the items and suddenly encounters an already specified view (aTabItem
) that is exactly of type of the item container (because for theTabControl
, a view for each viewmodel will be inserted in aTabItem
container). So WPF simply inserts theTabItem
into theTabControl
and notifies that it has not used anyItemTemplate
orItemTemplateSelector
for creating it.You could simply ignore this error, because in the end the control should look like you want it to (I suppose).
An alternative (and probably neater) way is not to mix views and viewmodels in one collection, but rather specify a "general" viewmodel for the "General" tab:
And of course you then need to tell WPF how to visualize it:
Update
To address the issues in your comments.
1. How do I bind the GeneralViewModel to the one that exist in my DataContext?
This is possible, but with some overhead. You have to create a binding proxy for this. (Take a look here.)
The second thing you will need is a markup extension:
Use this markup extension together with the binding proxy in your collection:
You can extend the markup extension as you like, e.g. in such a way that it can observe the object updates and replace the item in the target
CompositeCollection
.2. How do I specify general tab's header name?
You can use
ItemTemplate
s, but it becomes a little bit complicated. You have to implement aDataTemplateSelector
for yourTabControl
:Then you can define the different
ItemTemplate
s for differentTabItem
s:The question is: is this effort worth it or are you okay with that error message 26? You decide.