Reputation: 1109
I am trying to show different Groups in a Listview which contain an expander and a header. However I don't want my SecondLevel Group to show a header if the Group only contains 1 item. Since this would be quite inconvenient. My Code:
<Window x:Class="ListViewGrouping.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:listViewGrouping="clr-namespace:ListViewGrouping"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<listViewGrouping:GroupItemStyleSelector x:Key="groupItemStyleSelector"/>
<!-- Style for the first level GroupItem -->
<Style x:Key="FirstLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="3.5,0" Text="{Binding Name}" TextBlock.FontWeight="Bold"/>
<TextBlock Grid.Column="1" Margin="3.5,0" Text="Elements:"/>
<TextBlock Grid.Column="2" Margin="3.5,0" Text="{Binding ItemCount}"/>
</Grid>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for the second level GroupItem -->
<Style x:Key="SecondLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Margin="15,0,0,0">
<Expander.Header>
<TextBlock Text="{Binding Name}" TextBlock.FontWeight="Bold"/>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListView Name="mailView" ItemsSource="{Binding}">
<ListView.GroupStyle>
<GroupStyle ContainerStyleSelector="{StaticResource groupItemStyleSelector}" />
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}"/>
<GridViewColumn Header="Subject" DisplayMemberBinding="{Binding Subject}"/>
<GridViewColumn Header="Sender" DisplayMemberBinding="{Binding Sender}"/>
<GridViewColumn Header="Support-ID" DisplayMemberBinding="{Binding Support_ID}"/>
<GridViewColumn Header="Supporter" DisplayMemberBinding="{Binding Supporter}"/>
<GridViewColumn Header="Received" DisplayMemberBinding="{Binding ReceivedDate}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
Code behind:
private void createMailList()
{
_mails.Add(new Mail("LIC", "Lizenz geht nicht", "Xeun", "LIC.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Alles doof", "Xeun", "CD.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Re:Alles doof", "Xeun", "CD.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "CD kaputt", "Xeun", "CD.2013.01.10.003", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Geht nicht", "Xeun", "CD.2013.01.10.001", "Xeun", "25.09.2013"));
_mails.Add(new Mail("LIC", "Kaputt", "Xeun", "LIC.2013.01.10.001", "Xeun", "25.09.2013"));
}
public MainWindow()
{
InitializeComponent();
createMailList();
DataContext = _mails;
ICollectionView view = CollectionViewSource.GetDefaultView(_mails);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("ID");
view.GroupDescriptions.Add(groupDescription);
view.GroupDescriptions.Add(new PropertyGroupDescription("Support_ID"));
}
}
public class GroupItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
Style s;
CollectionViewGroup group = item as CollectionViewGroup;
Window window = Application.Current.MainWindow;
if (!group.IsBottomLevel)
{
s = window.FindResource("FirstLevel") as Style;
}
else
{
s = window.FindResource("SecondLevel") as Style;
}
return s;
}
}
I hope I explained my problem well enough - I have attached a screenshot of the small app - the Groups marked as red only contain one item and should not be shown as group.
Upvotes: 6
Views: 8067
Reputation: 211
here is my solution
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Expander IsExpanded="True">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="Visibility" Value="Visible"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ItemCount}" Value="1">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="Gray" FontSize="22" VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
<TextBlock Text=" item(s)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<Border BorderBrush="LightBlue" BorderThickness="2" Margin="0 2">
<ItemsPresenter />
</Border>
</Expander>
<ItemsPresenter>
<ItemsPresenter.Style>
<Style TargetType="ItemsPresenter">
<Setter Property="Visibility" Value="Collapsed"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ItemCount}" Value="1">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsPresenter.Style>
</ItemsPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
Upvotes: 0
Reputation: 12533
For both styles split the ControlTemplate in 2, one with an expander and one with out.
Create a converter which checks the if the group size (your group is of type CollectionViewGroup)
return yourGroup.Items.Count > 1
Place a DataTrigger as seen below in each style which checks the groups size via the converter (your DataContext is your group so the binding is Binding="{Binding}"
xaml :
<ControlTemplate TargetType="{x:Type GroupItem}" x:Key="withExpander">
<Expander IsExpanded="True">
<Expander.Header>
.....
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
<ControlTemplate TargetType="{x:Type GroupItem}" x:Key="withOutExpander">
<ItemsPresenter />
</ControlTemplate>
<Style x:Key="FirstLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template" Value="{StaticResource withExpander}" />
<Style.Triggers>
<DataTrigger Binding="{Binding , Converter={StaticResource GroupSizeToExpanderConverter}" Value="False">
<Setter Property="Template" Value="{StaticResource withOutExpander}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Edit :
*the converter value will be the Group itself (of type CollectionViewGroup)
The Converter :
public class GroupSizeToExpanderConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
CollectionViewGroup grp = (CollectionViewGroup)value;
return grp.Items.Count() > 1; // ALTERNATIVLY grp.ItemCount;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Upvotes: 12