How to apply different header and footer styles for different group levels?

Emon Haque 3,176 Reputation points
2021-01-27T03:36:46.01+00:00

Here's the output of a sample app with multilevel grouping:

60807-capture.png

Here's the link of the sample app. In that I've a DataTrigger for styling headers and footers which are not BottomLevel and as a result same style is applied to all those levels. What I want is to apply different header and footer styles for each of those 4 levels, for example:

Level1 - FontSize=20, FontWeight=Normal
Level2 - FontSize=18, FontWeight=Normal, Foreground=Gray
Level3 - FontSize=16, FontWeight=Normal, Foreground=LightBlue
Level4 - FontSize=14, FontWeight=Normal, Foreground=Red

How to do that?

Developer technologies Windows Presentation Foundation
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Emon Haque 3,176 Reputation points
    2021-01-28T05:07:35.41+00:00

    I've done it using two converters (HeaderConverter, HC and FooterConverter, FC) BUT I don't like the solution because it requires several nested if else and sets foreground and fontsize several times without any reason. With ContentControl in both header and footer:

    <ListBox.GroupStyle>  
        <GroupStyle>  
            <GroupStyle.ContainerStyle>  
                <Style TargetType="GroupItem">  
                    <Setter Property="Template">  
                        <Setter.Value>  
                            <ControlTemplate TargetType="GroupItem">  
                                <Grid>  
                                    <Grid.RowDefinitions>  
                                        <RowDefinition Height="Auto"/>  
                                        <RowDefinition Height="*"/>  
                                        <RowDefinition Height="Auto"/>  
                                    </Grid.RowDefinitions>  
                                    <ContentControl x:Name="header" Content="{Binding Converter={StaticResource HC}}" FontWeight="Bold"/>  
                                    <ItemsPresenter x:Name="items" Grid.Row="1" Margin="15 0 0 0"/>  
                                    <ContentControl x:Name="footer" Grid.Row="2" Content="{Binding Converter={StaticResource FC}}"/>  
                                </Grid>  
                            </ControlTemplate>  
                        </Setter.Value>  
                    </Setter>  
                </Style>  
            </GroupStyle.ContainerStyle>  
        </GroupStyle>  
    </ListBox.GroupStyle>  
    

    HC does these:

    public class HeaderConverter : IValueConverter  
    {  
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)  
        {  
            var group = value as CollectionViewGroup;  
            var header = new TextBlock() { Text = group.Name.ToString(), FontWeight = FontWeights.Bold };  
            if ((!group.IsBottomLevel))  
            {  
                foreach (CollectionViewGroup subGroup in group.Items)  
                {  
                    if (subGroup.IsBottomLevel)  
                    {  
                        header.Foreground = Brushes.Blue;  
                        header.FontSize = 12;  
                    }  
                    else  
                    {  
                        foreach (CollectionViewGroup sSubGroup in subGroup.Items)  
                        {  
                            if(sSubGroup.IsBottomLevel)  
                            {  
                                header.Foreground = Brushes.Green;  
                                header.FontSize = 14;  
                            }  
                            else  
                            {  
                                header.Foreground = Brushes.Red;  
                                header.FontSize = 16;  
                                header.Margin = new Thickness(0, 10, 0, 0);  
                            }  
                        }  
                    }  
                }  
            }  
            return header;  
        }  
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)  
        {  
            throw new NotImplementedException();  
        }  
    }  
    

    and FC these:

    public class FooterConverter : IValueConverter  
    {  
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)  
        {  
            int sum = 0;  
            var line = new Separator();  
            var sumBlock = new TextBlock() { HorizontalAlignment = HorizontalAlignment.Right, FontWeight = FontWeights.Bold };  
            var textBlock = new TextBlock() { FontWeight = FontWeights.Bold };  
    
            var group = value as CollectionViewGroup;  
    
            if (group.IsBottomLevel)  
            {  
                sum = ((IEnumerable<object>)group.Items).OfType<GroupedData>().Sum(x => x.Amount);  
                Grid.SetColumn(line, 1);  
            }  
    
            else  
            {  
                Grid.SetColumnSpan(line, 2);  
                foreach (CollectionViewGroup subGroup in group.Items)  
                {  
                    if (subGroup.IsBottomLevel)  
                    {  
                        sum += ((IEnumerable<object>)subGroup.Items).OfType<GroupedData>().Sum(x => x.Amount);  
                        sumBlock.Foreground = textBlock.Foreground = Brushes.Blue;  
                    }  
                    else  
                    {  
                        foreach (CollectionViewGroup sSubGroup in subGroup.Items)  
                        {  
                            if (sSubGroup.IsBottomLevel)  
                            {  
                                sum += ((IEnumerable<object>)sSubGroup.Items).OfType<GroupedData>().Sum(x => x.Amount);  
                                sumBlock.Foreground = textBlock.Foreground = Brushes.Green;  
                            }  
                            else  
                            {  
                                sumBlock.Foreground = textBlock.Foreground = Brushes.Red;  
                                foreach (CollectionViewGroup ssSubGroup in sSubGroup.Items)  
                                    sum += ((IEnumerable<object>)ssSubGroup.Items).OfType<GroupedData>().Sum(x => x.Amount);  
                            }  
                        }  
                    }  
                }  
            }  
            textBlock.Text = "Total " + group.Name.ToString();  
            sumBlock.Text = sum.ToString();  
            Grid.SetColumn(sumBlock, 1);  
    
            var grid = new Grid()  
            {  
                RowDefinitions =  
                {  
                    new RowDefinition(),  
                    new RowDefinition()  
                },  
                ColumnDefinitions =  
                {  
                    new ColumnDefinition(){ Width = new GridLength(1, GridUnitType.Star)},  
                    new ColumnDefinition(){Width = new GridLength(50)}  
                },  
                Children = { line, textBlock, sumBlock },  
                Resources =  
                {  
                    {  
                        typeof(TextBlock),  
                        new Style()  
                        {  
                            Setters =  
                            {  
                                new Setter()  
                                {  
                                    Property = Grid.RowProperty,  
                                    Value = 1  
                                }  
                            }  
                        }  
                    }  
                }  
            };  
            return grid;  
        }  
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)  
        {  
            throw new NotImplementedException();  
        }  
    }  
    

    and the output looks like this:

    61252-capture.png

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.