Reputation: 987
I have a List Components which is bound to a ListBox in xaml. In the view model, i am trying to use CollectionViewSource as follows :
var groupedItems = CollectionViewSource.GetDefaultView(Components);
groupedItems.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
groupedItems.GroupDescriptions.Add(new PropertyGroupDescription("SubCategory"));
Some of the object (T) in Components collection can have empty SubCategory. Now, when the UI is rendered, an empty header appears for grouping for objects which have empty SubCategory as shown below :
Category
--SubCategory
--Item 1
--Item 2
--
--Item 3
--Item 4
Category
......continues
I would like Item 3 & Item 4 which have no subcategory to appear as immediate child of Category as follows :
Category
--Item 3
--Item 4
--SubCategory
--Item 1
--Item 2
Category
......continues
Please guide on how to achieve this.
Regards,
Nish26
Upvotes: 1
Views: 2113
Reputation: 655
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 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
.
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>
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));
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; }
}
Upvotes: 2