New to Telerik UI for WPF? Download free 30-day trial

Style Aggregate Results Displayed in the GroupHeaderRow

Environment

Product RadGridView for WPF

Description

How to change the style of the aggregates based on the results.

Solution

The approach would differ depending on the value of the ColumnAggregatesAlignment property of the RadGridView. If its value is NoAlignment (which is the default), the aggregate results are shown in GridViewAggregateResultCell elements. If its value is NextToGroupKey or BelowToGroupKey, the results are displayed in GridViewGroupHeaderCell elements. This article will show how you can conditionally style both elements.

Example 1 demonstrates a sample model and viewmodel that will be used for demonstration purposes.

Example 1: The model and viewmodel

public class Product 
{ 
    public Product(string name, int id) 
    { 
        this.Name = name; 
        this.ID = id; 
    } 
    public string Name 
    { 
        get; 
        set; 
    } 
 
    public int ID 
    { 
        get; 
        set; 
    } 
 
    public static ObservableCollection<Product> GetProducts() 
    { 
        ObservableCollection<Product> products = new ObservableCollection<Product>(); 
        var id = 0; 
        for (int i = 1; i < 7; i++) 
        { 
            products.Add(new Product("Socks", ++id)); 
        } 
        products.Add(new Product("T-shirts", ++id)); 
        products.Add(new Product("Shoes", ++id)); 
        products.Add(new Product("Hats", ++id)); 
 
        return products; 
    } 
} 
 
public class ViewModel 
{ 
    private ObservableCollection<Product> products; 
 
    public ObservableCollection<Product> Products 
    { 
        get 
        { 
            if(this.products == null) 
            { 
                this.products = Product.GetProducts(); 
            } 
 
            return this.products; 
 
        } 
    } 
} 

Styling the GridViewAggregateResultCell elements

This approach is valid when the ColumnAggregatesAlignment of the RadGridView is NoAlignment. Example 2 shows how to create a style targeting GridViewAggregateResultCell and change its Background depending on its DataContext.

Example 2: Conditionally styling GridViewAggregateResultCell

<Grid> 
    <Grid.DataContext> 
        <local:ViewModel /> 
    </Grid.DataContext> 
 
    <Grid.Resources> 
        <local:AggregateResultsListItemCountToBackgroundConverter x:Key="AggregateResultsListItemCountToBackgroundConverter" /> 
 
        <!-- If you are using the NoXaml dlls, you should base the style on the default one for the theme like so--> 
        <!-- <Style TargetType="telerik:GridViewAggregateResultCell" BasedOn="{StaticResource GridViewAggregateResultCellStyle}">--> 
        <Style TargetType="telerik:GridViewAggregateResultCell"> 
            <Setter Property="Background" Value="{Binding ., Converter={StaticResource AggregateResultsListItemCountToBackgroundConverter}}" /> 
        </Style> 
    </Grid.Resources> 
    <telerik:RadGridView x:Name="grid" ColumnAggregatesAlignment="NoAlignment"  GroupRenderMode="Flat" ItemsSource="{Binding Products}" AutoGenerateColumns="False" > 
        <telerik:RadGridView.Columns> 
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}" Header="Product Name" /> 
            <telerik:GridViewDataColumn DataMemberBinding="{Binding ID}" > 
                <telerik:GridViewDataColumn.AggregateFunctions> 
                    <telerik:CountFunction Caption="Total: " /> 
                </telerik:GridViewDataColumn.AggregateFunctions> 
            </telerik:GridViewDataColumn> 
        </telerik:RadGridView.Columns> 
        <telerik:RadGridView.GroupDescriptors> 
            <telerik:ColumnGroupDescriptor Column="{Binding Path=Columns[\Name], ElementName=grid}" DisplayContent="Product Name" /> 
        </telerik:RadGridView.GroupDescriptors> 
    </telerik:RadGridView> 
</Grid> 

Example 3: AggregateResultsListItemCountToBackgroundConverter implementation

public class AggregateResultsListItemCountToBackgroundConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        var aggregateResult = value as AggregateResult; 
 
        if (aggregateResult.ItemCount <= 1) 
        { 
            return Brushes.Red; 
        } 
        else 
        { 
            return Brushes.Green; 
        } 
    } 
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        throw new NotImplementedException(); 
    } 
} 

Figure 1: Result from Example 2 in the Fluent theme

Styled aggregate results in the GroupHeaderRow

Styling the GridViewGroupHeaderCell elements

This approach is valid when the ColumnAggregatesAlignment of the RadGridView is NextToGroupKey or BelowToGroupKey. Example 4 shows how to create a style targeting GridViewGroupHeaderCell and change its Background depending on its DataContext.

Example 4: Conditionally styling GridViewGroupHeaderCell

<Grid> 
    <Grid.DataContext> 
        <local:ViewModel /> 
    </Grid.DataContext> 
 
    <Grid.Resources> 
        <local:IsNullConverter x:Key="IsNullConverter" /> 
        <local:ItemCountToBackgroundConverter x:Key="ItemCountToBackgroundConverter" /> 
 
        <!-- If you are using the NoXaml dlls, you should base the style on the default one for the theme like so--> 
        <!-- <Style TargetType="telerik:GridViewGroupHeaderCell" BasedOn="{StaticResource GridViewGroupHeaderCellStyle}">--> 
 
        <Style TargetType="telerik:GridViewGroupHeaderCell"> 
            <!-- Apply this style only to GridViewGroupHeaderCell elements that have some Content--> 
            <Style.Triggers> 
                <DataTrigger Binding="{Binding Content, Converter={StaticResource IsNullConverter}, RelativeSource={RelativeSource Mode=Self}}" Value="False"> 
                    <Setter Property="Background" Value="{Binding ., Converter={StaticResource ItemCountToBackgroundConverter}}" /> 
                </DataTrigger> 
            </Style.Triggers> 
        </Style> 
    </Grid.Resources> 
    <telerik:RadGridView x:Name="grid" ColumnAggregatesAlignment="NextToGroupKey"  GroupRenderMode="Flat" ItemsSource="{Binding Products}" AutoGenerateColumns="False" > 
        <telerik:RadGridView.Columns> 
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}" Header="Product Name" /> 
            <telerik:GridViewDataColumn DataMemberBinding="{Binding ID}" > 
                <telerik:GridViewDataColumn.AggregateFunctions> 
                    <telerik:CountFunction Caption="Total: " /> 
                </telerik:GridViewDataColumn.AggregateFunctions> 
            </telerik:GridViewDataColumn> 
        </telerik:RadGridView.Columns> 
        <telerik:RadGridView.GroupDescriptors> 
            <telerik:ColumnGroupDescriptor Column="{Binding Path=Columns[\Name], ElementName=grid}" DisplayContent="Product Name" /> 
        </telerik:RadGridView.GroupDescriptors> 
    </telerik:RadGridView> 
</Grid> 

Example 5: Implementation of converters used in Example 4

public class ItemCountToBackgroundConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        var group = value as QueryableCollectionViewGroup; 
 
        if (group.ItemCount > 5) 
        { 
            return Brushes.Green; 
        } 
        else 
        { 
            return Brushes.Red; 
        } 
    } 
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        throw new NotImplementedException(); 
    } 
} 
 
public class IsNullConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        return value == null; 
    } 
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
        throw new InvalidOperationException("IsNullConverter can only be used OneWay."); 
    } 
} 

Figure 2: Result from Example 3 in the Fluent theme

Styled aggregate results in the GroupHeaderRow