This answer describes approach based on style selectors. Perhaps, there are better ways to achieve similar results, I'd look on them with pleasure.
Style selector
Style selectors allows to apply a style based on custom logic.
The following selector should check whether the Name of CollectionViewGroup is null and return corresponding style:
public class GroupStyleSelector : StyleSelector
{
public Style NoGroupHeaderStyle { get; set; }
public Style DefaultGroupStyle { get; set; }
public override Style SelectStyle(object item, DependencyObject container)
{
var group = item as CollectionViewGroup;
if (group?.Name == null /* or any other condition */)
{
return NoGroupHeaderStyle;
}
return DefaultGroupStyle;
}
}
Worth mentioning that if the style is null, the default one will be used. Hence, it is important to set NoGroupHeaderStyle.
XAML
A style for the GroupItem that should not show group header:
<Style TargetType="{x:Type GroupItem}" x:Key="NoGroupHeaderStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<ItemsPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The default style for GroupItem with header. It's optional.
<Style TargetType="{x:Type GroupItem}" x:Key="DefaultGroupHeaderStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" />
<ItemsPresenter Grid.Row="1" Margin="20,0,0,0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The style selector that was described above:
<local:GroupStyleSelector x:Key="GroupStyleSelector"
NoGroupHeaderStyle="{StaticResource NoGroupHeaderStyle}"
DefaultGroupStyle="{StaticResource DefaultGroupHeaderStyle}" />
Due to the custom style of GroupItem, which is provided by style selector, the group header will not appear for those items, whose SubCategory is null:
<ListBox ItemsSource="{Binding GroupedItems}" DisplayMemberPath="ComponentName">
<ListBox.GroupStyle>
<GroupStyle ContainerStyleSelector="{StaticResource GroupStyleSelector}">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<!-- Display the name of CollectionViewGroup -->
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
</ListBox>
Sorting
In order to show items with empty SubCategory first, they should be sorted by their SubCategory:
CollectionView.SortDescriptions.Add(
new SortDescription(nameof(Component.SubCategory),
ListSortDirection.Ascending));
Component
The following class was used as an element in the collection:
public class Component
{
public string ComponentName { get; set; }
public string Category { get; set; }
public string SubCategory { get; set; }
}