Search code examples
wpfwpfdatagrid

WPF Datagrid Grouping , displaying autogenrated columns


I am working on a wpf datagrid which is bound to a collection of following class

public class SalesData
{
    public string SalesManName{ get; set; }
    public int salesCount{ get; set; }
    public string Area { get; set; }
    public datetime salesdate{get;set;}            
    public int avgSales{ get; set; }
}

on the click of a button in my UI , I am doing the following operation

CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(Datagrid.ItemsSource);
view.SortDescriptions.Add(new SortDescription("SalesCount", ListSortDirection.Descending));

PropertyGroupDescription groupDescription = new PropertyGroupDescription("SalesManName");

PropertyGroupDescription groupDescription2 = new PropertyGroupDescription("salesdate");

Now if What basically happens is it gives me the following result in the datagrid

SalesManName | SalesCount | Area   | SalesDate  
AAA          | 2          | London | 05/06/2017 
AAA          | 1          | London | 05/07/2017 
AAA          | 1          | London | 05/08/2017 
AAA          | 2          | London | 05/09/2017 
BBB          | 2          | London | 05/06/2017 
BBB          | 2          | London | 05/07/2017 
BBB          | 2          | London | 05/09/2017 

What i would like to have is

SalesManName | 05/06/2017  | 05/07/2017  | 05/08/2017  | 05/09/2017 
AAA          | 2           |     1       |     1       |   2
BBB          | 2           |     2       |     0       |   2

Solution

  • I did the same long time ago. Unfortunately I can't recall the post that helped me. The idea consists of using a DataTable as the ItemsSource of a DataGrid with the converter that will build the datatable. Xaml

    <DataGrid GridLinesVisibility="None" ItemsSource="{Binding AllItems, Converter={StaticResource SalesDataConverter}, Mode=OneWay}" IsReadOnly="True" />
    

    Where AllItems is an ObservableCollection of SalesData

    Converter

    public class SalesDataConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var dataTable = new DataTable();
            const string format = "MM/dd/yyyy";
    
            var allSalesData = value as IEnumerable<SalesData>;
            var headers = allSalesData.Select(s => s.SalesDate.ToString(format)).Distinct();
    
            dataTable.Columns.Add("SalesManName");
            foreach (var header in headers)
            {
                dataTable.Columns.Add(new DataColumn(header, typeof(string)));
            }
    
            var saleDico = allSalesData.GroupBy(s => s.SalesManName)
                .Select(g => new
                {
                    SalesManName = g.Key,
                    DateAndCount = g.ToList().GroupBy(i => i.SalesDate.ToString(format))
                    .ToDictionary(e => e.Key, e => e.ToList().Sum(f => f.SalesCount))
                });
    
            foreach (var item in saleDico)
            {
                var values = new List<string>() { item.SalesManName };
                int count;
                foreach (var h in headers)
                {
                    var val = item.DateAndCount.TryGetValue(h, out count) ? count.ToString() : string.Empty;
                    values.Add(val);           
                }
                dataTable.Rows.Add(values.ToArray());
            }
            return dataTable.AsDataView();
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }