murkr
murkr

Reputation: 694

c# / XAML - ListView grouping: Changing the (background) color of the first header only

In my WPF Application, I have this ListView:

<ListView.GroupStyle>
  <GroupStyle>
    <GroupStyle.ContainerStyle>
      <Style TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate>
              <Expander IsExpanded="True">
                <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=" Ergebnis(se)" FontSize="22"
                               Foreground="Silver" FontStyle="Italic"
                               VerticalAlignment="Bottom"/>
                  </StackPanel>
                </Expander.Header>
                <ItemsPresenter/>
              </Expander>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </GroupStyle.ContainerStyle>
  </GroupStyle>
</ListView.GroupStyle> 

Now I want the first - and only the first - Header to appear in a different color (than the rest of the Headers - Font Color or Background Color, I don't care) for it to be marked. I can't for the hell of it come up with an idea on how to do it.

Upvotes: 0

Views: 1083

Answers (2)

Vimal CK
Vimal CK

Reputation: 3563

Converter in WPF is very costly as it will execute for each ListViewItem. Since the requirement is to apply style always for the first item, VisualTreeHelper will be best fit for the solution.

var expander = GetElement<Expander>(myListView);
// Do expander style changes

Below is a generic method to get the element from the Visual Tree.

public T GetElement<T>(Visual element)
{
        T foundElement = default(T);
        if (element == null) return foundElement;
        if (element.GetType() == typeof(T)) return (T)Convert.ChangeType(element, typeof(T));

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
        {
            Visual visual = VisualTreeHelper.GetChild(element, i) as Visual;
            foundElement = GetElement<T>(visual);
            if (foundElement != null) break;
        }
        return foundElement;
    }

Upvotes: 0

mm8
mm8

Reputation: 169200

You could use a converter class that returns a specific Brush for the first group only:

public class GroupConverter : IValueConverter
{
    int n;
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return n++ == 0 ? Brushes.Yellow  : Brushes.Transparent;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML:

<ListView x:Name="lv">
    <ListView.Resources>
        <local:GroupConverter x:Key="converter" />
    </ListView.Resources>
    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Expander IsExpanded="True" Background="{Binding Path=., Converter={StaticResource converter}}">
                                    <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=" Ergebnis(se)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
                                        </StackPanel>
                                    </Expander.Header>
                                    <Grid Background="White">
                                        <ItemsPresenter />
                                    </Grid>
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </ListView.GroupStyle>
</ListView>

Upvotes: 1

Related Questions