wpfxamlmvvmtabcontrolcollectionviewsource

Use CollectionViewSource with TabControl


I'm trying to group and display the items of an ObservableCollection, just by using XAML code. It works well using a simple CollectionViewSource and a ListBox[1].

Actually, I would prefer to display the group's content in a tabcontrol. Google led me to the following social.msdn article which presents a workaround to display the groups as a TabControl using code behind:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/e073f275-0826-4fca-b9da-e310ccf1713e/wpf-grouping?forum=wpf

However, as I'm using MVVM and must rely on xaml only, I can't get it to work. Actually, the CollectionViewSource populates the groups (the TabControl shows the correct tabItemHeaders), but clicking on any of these TabItems freezes the application. Here's what I've tried:

    <StackPanel x:Key="ModulSelectInputParameterView">
    <StackPanel.Resources>
        <CollectionViewSource x:Key="cvs" x:Name="collectionViewSource" Source="{Binding ReferencedLmtItem.ModulInputParameterCollection }">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Category"/>
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </StackPanel.Resources>

    <Grid >
        <TabControl ItemsSource="{Binding Source={StaticResource cvs}, Path=Groups, Mode=OneWay}" DataContext="{Binding Source={StaticResource cvs}, Mode=OneWay}">
            <!-- First Level -->
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <ListBox ItemsSource="{Binding Items}">
                         Second Level 
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Expander Header="{Binding Name}">
                                    <ListBox ItemsSource="{Binding Items}">
                                         The Item of the Collection 
                                        <ListBox.ItemTemplate>
                                            <DataTemplate>
                                                <StackPanel Orientation="Horizontal">
                                                    <TextBlock Text="{Binding Key}"/>
                                                    <TextBlock Text=" - "/>
                                                    <TextBlock Text="{Binding Value.Comment}"/>
                                                </StackPanel>
                                            </DataTemplate>
                                        </ListBox.ItemTemplate>
                                    </ListBox>
                                </Expander>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>

</StackPanel>

[1]: This piece of xaml does work as expected, but uses a wrappanel to display groups contents:

<StackPanel x:Key="ModulSelectInputParameterView">
    <StackPanel.Resources>
        <CollectionViewSource x:Key="cvs" x:Name="collectionViewSource" Source="{Binding ReferencedLmtItem.ModulInputParameterCollection }">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Category"/>
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </StackPanel.Resources>
    
    <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" VerticalContentAlignment="Top" ItemContainerStyle="{StaticResource ModulSelectInputParameterListBoxItemContainerStyle}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ListBox.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <Border BorderBrush="DarkGray" BorderThickness="2" Margin="2">
                            <TextBlock FontWeight="Bold" FontSize="14" Text="{Binding Path=Name}" HorizontalAlignment="Center" MinWidth="100"/>
                        </Border>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
                <GroupStyle.Panel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal" Margin="2"/>
                    </ItemsPanelTemplate>
                </GroupStyle.Panel>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
                        <Setter Property="Control.Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <Border BorderThickness="2" BorderBrush="DarkGray">
                                        <StackPanel>
                                            <ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" />
                                            <ItemsPresenter Margin="2,0,2,2" />
                                        </StackPanel>
                                    </Border>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>

        </ListBox.GroupStyle>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True" Orientation="Vertical" VerticalAlignment="Top"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>

    </ListBox>
</StackPanel>

Solution

  • Thanks to Joh who helped with the appropriate DataBinding. However, the reason was totally different, a quick and dirty solution is given below[1]:

    Basically, I was missing that the above mentioned tab control is nested within an outer Tab Control in my main window. I am not toally sure if the following description is entirely correct[1], but to my mind the reason is the following:

    [1] Defining an empty style in the inenr tabControl.Resources solved the problem:

    <TabControl.Resources>
                    <Style TargetType="TabItem">
    
                    </Style>
                </TabControl.Resources>
    

    I would be happy if someone could confirm this idea or provide some links to well known issues with shared styles in nested controls.