DataGridView Grouping in C#/VB.NET: Two Recipes
by Igor Katenov, the lead developer at 10Tec
DataGridView grouping is a very popular topic on many forums and websites dedicated to WinForms controls. The popularity of this topic is due to the fact that the .NET Framework does not give the developers any native ability to create group rows in WinForms DataGridView.
We analyzed existing source code solutions of this problem and place our overview of two of them below. At the end of this article you will also find a brief description of the grouping functionality in our DataGridView-like control named iGrid.NET.
DataGridViewGrouper component: adding group rows to WinForms DataGridView
If you search the Internet using a query like winforms datagridview grouping, most likely, you will find the following free open-source project in the top search results: DataGridViewGrouper. This component is a class that can be attached to a DataGridView in any existing form to add the grouping functionality to DataGridView. The DataGridViewGrouper component can be compiled as a standalone assembly to implement DataGridView grouping in C# and VB.NET or any other popular .NET language.
Here is an example of how it looks if we attach the component to a WinForms DataGridView with some test data:
As you can see from the picture, this helper class automatically adds group rows to a DataGridView, and the user can even collapse/expand them using the plus-minus buttons inside group rows.
The usage of this class is also simple. From code, you just need two lines like the following ones to attach the class to a DataGridView and group it by the specified column:
var grouper = new DataGridViewGrouper(dataGridView1);
grouper.SetGroupOn("Patient");
If the class is compiled as a component and added to a VB.NET or C# project, you drop it on a form and link to the target DataGridView using the property of the same name.
DataGridViewGrouper provides you with some settings you can use to adjust the DataGridView grouping process. It also triggers useful events like GroupingChanged
or DisplayGroup
so you can be notified about what's happening and even enhance the contents of group rows in your DataGridView using C# or VB.NET.
The idea of the DataGridView grouping functionality implemented in the class is based on the RowPrePaint
/RowPostPaint
events of the DataGridView control. They are used to draw the contents of group rows inside the target DataGridView.
This grouping approach is good but has some serious restrictions though. The main of them is that the target DataGridView control should be data-bound, i.e. it should display data from a data source specified in the DataSource
property. Another significant restriction is the ability to group the grid only by the values from one column.
The drawing of group rows in this DataGridView grouping is odd a little bit. They are drawn using the whole width of the grid, even if the total width of all columns is less than the width of the control. To overcome this, you should modify the original source code. And one more bad thing regarding drawing: you can notice some glitches when drawing the cell contents, especially in the last row.
Vertical cell merging instead of row grouping
Let's look at another approach to the WinForms DataGridView grouping task:
The good old MSFlexGrid control supplied with the classic Visual Basic implements the ability to combine cells with repeated values in columns into one big cell, and this idea can be used to solve the task of row grouping in DataGridView. Rows belonging to one group can be joined visually with merged cells - instead of using classical horizontal group rows. Here is a link to the VB.NET implementation of this DataGridView grouping concept (you can find the link to the original C# DataGridView grouping code on that page too).
This great idea works for both data-bound and unbound DataGridViews. Its implementation is very simple and is based on custom drawing, when unneeded cell borders are just removed when painting the cells. Here is the core procedure of this DataGridView grouping implementation (C#):
protected override void OnCellPainting(
DataGridViewCellPaintingEventArgs args)
{
base.OnCellPainting(args);
args.AdvancedBorderStyle.Bottom =
DataGridViewAdvancedCellBorderStyle.None;
// Ignore column and row headers and first row
if (args.RowIndex < 1 || args.ColumnIndex < 0)
return;
if (IsRepeatedCellValue(args.RowIndex, args.ColumnIndex))
{
args.AdvancedBorderStyle.Top =
DataGridViewAdvancedCellBorderStyle.None;
}
else
{
args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top;
}
}
If we compare this solution to the previous one that adds group rows to WinForms DataGridView, you may think that the idea with combined cells can be used to group DataGridView by several columns. Yes, this idea will work, but only in the case if group values of the second and deeper group levels do not repeat outside of higher group levels. Note also that the merged DataGridView cells representing group rows do not act like one joined cell and do not provide you with the collapse/expand functionality. These drawbacks are discussed in greater detail in another article on this website, How to Merge Cells in DataGridView.
In any case, the source code of this DataGridView grouping in C#/VB.NET is available, and you can try to modify it to add the missing features by yourself.
iGrid.NET: grouping in a DataGridView-like grid
As we wrote earlier in this article, our WinForms grid can be used as a powerful DataGridView replacement in many real-world applications. Let's list the main benefits of the iGrid usage from the point of view of grouping. The accompanying screenshot will be the following:
- Row grouping can be done in the visual interface, and no code is required to make it work. The group box over the main grid area is used for this purpose.
- The grouped columns can be sorted ascending/descending together with other columns sorted in the grid.
- You can optionally set the columns you group by to be visible in the grid.
- Group rows can be collapsed/expanded interactively or from code, and this operation is lightning even in grids with 10,000+ rows.
- Various criteria can be specified to create group rows. These can be simple string or date groups, or grouping by images or fonts.
- You can also code such special cases of grouping when group rows are created for intervals of values - like for message sizes on the screenshot above.
- The group rows in iGrid are drawn with the same routines used for iGrid cells, and all formatting options (text trimming, word wrapping, personalized fonts and colors) are available for them.
- The developer has full control over the grouping process through the corresponding set of events (creation of every group row, beginning of new grouping, collapsing or expanding a group row, etc.)
As a conclusion, we would like to say that the C#/VB.NET DataGridView grouping solutions mentioned in this article aren't supported and provided "as is" so they can be used as a free basis in your developments. From the other side, iGrid.NET as a WinForms DataGridView replacement with built-in grouping functionality can save a lot of your time and give you more features in your real-world applications for a reasonable price. Our support service is also at your disposal at any time if you have any questions regarding the product.