Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display sum of grouped items in ListView

I'm creating a WPF TimeCard app using the MVVM design pattern, and I'm trying to display the sum (total) hours the user has clocked in grouped by each day. I have a ListView with all of the TimeCard data broken into groups using the following XAML:

<ListView.GroupStyle>
    <GroupStyle ContainerStyle="{StaticResource GroupItemStyle}">
        <GroupStyle.HeaderTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Name, StringFormat=\{0:D\}}" FontWeight="Bold"/>
                    <TextBlock Text="  (" FontWeight="Bold"/>
                    <!-- This needs to display the sum of the hours -->
                    <TextBlock Text="{Binding ???}" FontWeight="Bold"/>
                    <TextBlock Text=" hours)" FontWeight="Bold"/>
                </StackPanel>
            </DataTemplate>
        </GroupStyle.HeaderTemplate>
    </GroupStyle>
</ListView.GroupStyle>

Is this even possible? At first I thought I would create a partial class of the CollectionViewGroup and add my own properties. But I'm not sure this will even work. Perhaps there is a better solution... any suggestions?

like image 470
Brent Avatar asked Feb 06 '10 04:02

Brent


2 Answers

To expand on what e.tadeu said, you can bind your HeaderTemplate's DataTemplate to the Items property of the CollectionViewGroup. This will return you all of the items that are in the current group.

Then you can supply a converter that will return you the desired data from that collection of items. In your case, you say you want the sum of the hours. You could implement a converter that does something like:

public class GroupHoursConverter : IValueConverter
{

    public object Convert(object value, System.Type targetType, 
                          object parameter, 
                          System.Globalization.CultureInfo culture)
    {
        if (null == value)
            return "null";

        ReadOnlyObservableCollection<object> items = 
              (ReadOnlyObservableCollection<object>)value;

        var hours = (from i in items
                     select ((TimeCard)i).Hours).Sum();

        return "Total Hours: " + hours.ToString();
    }

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

Then you could use this converter on your data template:

    <Window.Resources>
        <local:GroupHoursConverter  x:Key="myConverter" />
    </Window.Resources>

    <ListView.GroupStyle>
        <GroupStyle ContainerStyle="{StaticResource GroupItemStyle}">
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Name, 
                                                  StringFormat=\{0:D\}}" 
                                   FontWeight="Bold"/>
                        <TextBlock Text="  (" FontWeight="Bold"/>
                        <!-- This needs to display the sum of the hours -->
                        <TextBlock Text="{Binding Path=Items, 
                                         Converter={StaticResource myConverter}}"
                                   FontWeight="Bold"/>
                        <TextBlock Text=" hours)" FontWeight="Bold"/>
                    </StackPanel>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </ListView.GroupStyle>

Cheers!

like image 145
NathanAW Avatar answered Nov 07 '22 13:11

NathanAW


Use a Converter.

See:

http://www.codeproject.com/KB/WPF/WPFAggregateConverter.aspx

This might help you too:

http://www.codeproject.com/KB/WPF/DsxGridCtrl.aspx

like image 30
e.tadeu Avatar answered Nov 07 '22 13:11

e.tadeu