I'm implementing a WPF DataGrid that contains projects with many key figures. Projects are grouped by project categories.
For each category there should be:
- a row that shows in each key figure column sum of all rows for the column.
- a target row that is not part of the datasource grid in binded to. target row tells for every column what is target for the year (e.g. how much money there's to spend).
These rows should be always on top in each group (sorting filtering).
My 1st solution was to have this data in group header. This is not a good solution because group header does not support columns. i.e. it should be constructed by getting column widths.
That could be done but it gets complicated when users want to reorder and hide columns.
DataGrid is using CollectionViewSource so it's not populated with C# code. Basically i'm extending this example: http://msdn.microsoft.com/en-us/library/ff407126.aspx
Thanks & Best Regards - matti
I have a hacked-together DataGrid with group subtotal rows in one of my projects. We weren't concerned about some of the issues you bring up, such as hiding and sorting columns so I don't know for sure if it can be extended for that. I also realize there could be performance issues that may be a problem with large sets (my window is operating 32 separate DataGrids - ouch). But it's a different direction from other solutions I've seen, so I thought I'd throw it up here and see if it helps you out.
My solution consists of 2 major components:
1. The subtotal rows aren't rows in the main DataGrid, but are separate DataGrids. I have 2 extra grids in each group actually: 1 in the header that is only displayed when the group is collapsed, and one beneath the ItemsPresenter. The ItemsSource for the subtotal DataGrids comes from a Converter that takes the items in the group and returns an aggregate view model. The columns of the subtotal grids are exactly the same as the main grid (filled out in DataGrid_Loaded, though I'm sure it could be done in xaml too).
2. Then the issue is how to get all DataGrids to behave as if they were a single grid. I've handled that by subclassing
DataGridTextColumn
(we only have text in this case, but other column types should work too) in a class calledDataGridSharedSizeTextColumn
that mimics the SharedSizeGroup behavior of the Grid class. It has a string dependency property with a group name and keeps track of all columns in the same group. WhenWidth.DesiredValue
changes in one column, I update the MinWidth in all the other columns and force an update withDataGridOwner.UpdateLayout()
. This class is also covering column reordering and does a group-wide update whenever DisplayIndex changes. I would think this method would also work with any other column property as long as it has a setter.There were other annoying things to work out with selection, copying, etc. But it turned out to be pretty easy to handle with MouseEntered and MouseLeave events and by using a custom Copy command.
One option could be to add the rows in data source with special values for Name and other fields that do not make sense and use DataTrigger to show them with special colors and maybe some other.
Filtering is done in C# anyway so it doesn't affect these rows.
Sorting is the only problem here. It would be so cool just to tell that some rows are always with order 0 and with order 1 in the group. But cause i dunno how to do it I gotta make custom sorting in C# for all the columns instead of just declaring the sorting:
EDIT: On top of everything else it has a major drawback comparing to my 1st solution (sum info in group header) because when filtering changes I should update the sums to be calculated only for visible rows.
So this answer is a complete hack and lacks all the elegance and uses no nice features that WPF is suppose to have :(