Oscar
Oscar

Reputation: 1147

How can I add a value when I use groupping by in DataGrid

I'd like to show the average score in each group. I think I need to add a converter in the control template, actually I don't how does it work.

        <DataGrid Name="dataGrid1" ItemsSource="{Binding List}" AutoGenerateColumns="True" Grid.ColumnSpan="4" Grid.RowSpan="21">
        <DataGrid.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Padding="3"/>
                        </StackPanel>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <Expander>
                                        <Expander.Header>
                                            <StackPanel Orientation="Horizontal">
                                                <TextBlock Text="{Binding Path=Name}" />
                                                <TextBlock Text="{Binding Path=ItemCount}" Margin="8,0,4,0"/>
                                                <TextBlock Text="Items" Margin="8,0,4,0"/>
                                            </StackPanel>
                                        </Expander.Header>
                                        <ItemsPresenter />
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </DataGrid.GroupStyle>
    </DataGrid>

This the code an example code which I'm doing tests:

public enum KindOfPerson
{
    Student, Teacher, ...
}

public class Person
{
    // This contains only numbers between 0 and 1
    public double ScorePercent { get; set; }
    public KindOfPerson Type { get; set; }
}

I'm groupping by KindOfPerson

Upvotes: 0

Views: 143

Answers (1)

brunnerh
brunnerh

Reputation: 184376

You can indeed use a converter, here would be an example:

<!-- The additional binding to ItemsCount is used to get the binding updated if new items are added, maybe there is a cleaner and easier way -->
<TextBlock>
    <TextBlock.Text>
        <MultiBinding>
            <MultiBinding.Converter>
                <vc:MeanConverter PropertyName="ScorePercent" />
            </MultiBinding.Converter>
            <Binding Path="Items" />
            <Binding Path="ItemCount" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>
// Note that this code might be quite the crap, it's just a sketchy example implementation.
public class MeanConverter : IMultiValueConverter
{
    /// <summary>
    /// Name of the property which should be evaluated.
    /// </summary>
    public string PropertyName { get; set; }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var items = values[0] as ReadOnlyObservableCollection<object>;
        double accscore = 0;
        PropertyInfo property = null;
        foreach (var item in items)
        {
            if (property == null)
            {
                property = item.GetType().GetProperty(PropertyName);
            }
            var value = property.GetValue(item, null);
            accscore += (double)System.Convert.ChangeType(value, typeof(double));
        }
        var output = accscore/items.Count;
        return output.ToString();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Upvotes: 1

Related Questions