A
A
Alexander2015-02-15 23:02:07
.NET
Alexander, 2015-02-15 23:02:07

How to group data in an Observalble Collection and bind it to a DataGrid (C# + WPF)?

There is an ObservableCollection that stores the following data:

public class StatisticsModel : ObservableObject
{
  private long incomingTraffic;
  private long outcomingTraffic;
  private string time;
  
  public string Time
  {
    get { return this.time; }
    set { this.Set("Time", ref this.time, value); }
  }

  public long IncomingTraffic
  {
    get { return this.incomingTraffic; }
    set { this.Set("IncomingTraffic", ref this.incomingTraffic, value); }
  }

  public long OutcomingTraffic
  {
    get { return this.outcomingTraffic; }
    set { this.Set("OutcomingTraffic", ref this.outcomingTraffic, value); }
  }
}

There is a ViewModel where DispatchingObservableCollection is nothing more than a thread-safe ObservableCollection. and network.Statistics is essentially part of the implementation of the Observer pattern:
public class StatisticsViewModel : ViewModelBase
{
  private DispatchingObservableCollection<StatisticsModel> statisticsCollection;

  public StatisticsViewModel(INetwork network)
  {
    this.statisticsCollection = new DispatchingObservableCollection<StatisticsModel>();

    network.Service.Statistics += stats => this.StatisticsCollection.Add(Mapper.Map<StatisticsModel>(stats));
  }

  public DispatchingObservableCollection<StatisticsModel> StatisticsCollection
  {
    get { return this.statisticsCollection; }
    set { this.Set("StatisticsCollection", ref this.statisticsCollection, value); }
  }
}

And there is also a View:
<Window DataContext="{Binding Statistics, Source={StaticResource Locator}}"	...>
    <Grid>
    ...
        <DataGrid ItemsSource="{Binding StatisticsCollection}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Time}" Header="Время"/>
                <DataGridTextColumn Binding="{Binding IncomingTraffic}" Header="Входящий траффик"/>
                <DataGridTextColumn Binding="{Binding OutcomingTraffic}" Header="Исходящий траффик"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Data from the server comes like this:
{ Time: "00:00:01", IncomingTraffic: 100, OutcomingTraffic: 0 },
{ Time: "00:00:01", IncomingTraffic: 0, OutcomingTraffic: 100 },
{ Time: "00:00:01", IncomingTraffic: 100, OutcomingTraffic: 0 },
{ Time: "00:00:02", IncomingTraffic: 100, OutcomingTraffic: 0 },
{ Time: "00:00:02", IncomingTraffic: 0, OutcomingTraffic: 100 }

In fact, the whole thing is perfectly grouped:
this.statisticsCollection.GroupBy(x => x.Time)
  .Select(
    y =>
    new StatisticsModel
      {
        Time = y.First().Time,
        IncomingTraffic = y.Sum(z => z.IncomingTraffic),
        OutcomingTraffic = y.Sum(z => z.OutcomingTraffic)
      });

The only question that remains is how to use this grouped data. I did not manage to bind them to the DataGrid. Or should other means be used for the data received during the execution of the program?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sumor, 2015-02-16
@AlexTGM

If you need to group the source data (show by groups). There is a grouping mechanism built into WPF for this. An example of its use is described on MSDN . The main point - you describe the description of the CollectionViewSource, which takes the source data as a source, and then in the CollectionViewSource you specify the property by which to group. In the DataGrid, the generated CollectionViewSource is specified as input. Additionally, it is possible to describe the presentation template of the grouped data.
If you want to display exactly the StatisticsModel list. To do this, you just need to dynamically assign the result of your last construction to the Source property of the DataGrid object this.statisticsCollection.GroupBy(...).Select(...)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question