Known affected versions: 2015.2.728, 2016.1.217, both net40 and net45
There appears to be a bug in the CommonHeaderPresenter VirtualizingStrategy when there are more than 2 levels of nested column groups.
The following code shows the bug in effect. When EnableColumnGroupsVirtualization is True, the Middle 2 group headers are not displayed. Only the outermost group (not referenced by any column) and the innermost group (referenced by the single column) are visible. (Also see attached image for demonstration)
01.
<
Window
02.
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
03.
x:Class
=
"chartTest.MainWindow"
05.
xmlns:x
=
"http://schemas.microsoft.com/winfx/2006/xaml"
06.
xmlns:d
=
"http://schemas.microsoft.com/expression/blend/2008"
07.
xmlns:mc
=
"http://schemas.openxmlformats.org/markup-compatibility/2006"
08.
mc:Ignorable
=
"d"
09.
Title
=
"MainWindow"
10.
Height
=
"350"
11.
Width
=
"525"
>
12.
<
telerik:RadGridView
13.
AutoGenerateColumns
=
"False"
14.
CanUserDeleteRows
=
"False"
15.
CanUserSortColumns
=
"False"
16.
CanUserResizeColumns
=
"False"
17.
CanUserReorderColumns
=
"False"
18.
CanUserResizeRows
=
"False"
19.
CanUserFreezeColumns
=
"False"
20.
CanUserInsertRows
=
"False"
21.
CanUserSelect
=
"True"
22.
CanUserSortGroups
=
"False"
23.
ShowGroupPanel
=
"False"
24.
NewRowPosition
=
"None"
25.
ShowColumnFooters
=
"False"
26.
RowIndicatorVisibility
=
"Collapsed"
27.
EnableColumnGroupsVirtualization
=
"True"
>
28.
<!-- Switch EnableColumnGroupsVirtualization between True and False to see the bug -->
29.
<
telerik:RadGridView.ColumnGroups
>
30.
<
telerik:GridViewColumnGroup
31.
Name
=
"Outermost Group"
32.
Header
=
"Outermost Group"
>
33.
<!-- These 2 middle groups do not show up when virtualization is used -->
34.
<
telerik:GridViewColumnGroup
35.
Name
=
"Middle 1 Group"
36.
Header
=
"Middle 1 Group"
>
37.
<
telerik:GridViewColumnGroup
38.
Name
=
"Middle 2 Group"
39.
Header
=
"Middle 2 Group"
>
40.
<
telerik:GridViewColumnGroup
41.
Name
=
"Innermost Group"
42.
Header
=
"Innermost Group"
>
43.
</
telerik:GridViewColumnGroup
>
44.
</
telerik:GridViewColumnGroup
>
45.
</
telerik:GridViewColumnGroup
>
46.
</
telerik:GridViewColumnGroup
>
47.
</
telerik:RadGridView.ColumnGroups
>
48.
<
telerik:RadGridView.Columns
>
49.
<
telerik:GridViewColumn
50.
Width
=
"150"
51.
ColumnGroupName
=
"Innermost Group"
/>
52.
</
telerik:RadGridView.Columns
>
53.
</
telerik:RadGridView
>
54.
</
Window
>
I have tracked it down to the InitializeVisuals() method on VirtualizingStrategy (Controls\GridView\GridView\GridView\ColumnGroups\CommonHeaderPresenter.VirtualizingStrategy.cs).
At around line 69 it traverses the column groups for the current column group, and sets each child control's ParentGroup property to the TOP LEVEL (outermost) column group. Thus all child groups at all levels are flattened out as they are made direct children of the first level of column groups:
01.
foreach
(var columnGroup
in
ParentPresenter.ColumnGroups)
02.
{
03.
...
04.
05.
this
.TraverseColumnGroups(columnGroup,
06.
new
Action<GridViewColumnGroup>((c) =>
07.
{
08.
if
(!
this
.GroupNames.Contains(c.Name))
09.
{
10.
this
.GroupNames.Add(c.Name);
11.
c.ParentGroup = columnGroup;
12.
c.DataControl = columnGroup.DataControl;
13.
}
14.
}));
15.
}
I have managed to fix this by creating an overload for TraverseColumnGroups which takes an action which can act on both the Parent AND Child groups. Using this new action in the traversal from above results in the inner column group headers actually showing up in the test code from above.
The changes I had to make can be seen below (unrelated code excluded):
01.
internal
void
TraverseColumnGroups(GridViewColumnGroup group, Action<GridViewColumnGroup, GridViewColumnGroup> action)
02.
{
03.
foreach
(var childGroup
in
group.ChildGroups)
04.
{
05.
action.Invoke(group, childGroup);
06.
this
.TraverseColumnGroups(childGroup, action);
07.
}
08.
}
09.
10.
...
11.
12.
foreach
(var columnGroup
in
ParentPresenter.ColumnGroups)
13.
{
14.
...
15.
16.
this
.TraverseColumnGroups(columnGroup,
17.
new
Action<GridViewColumnGroup, GridViewColumnGroup>((parentGroup, childGroup) =>
18.
{
19.
if
(!
this
.GroupNames.Contains(childGroup.Name))
20.
{
21.
this
.GroupNames.Add(childGroup.Name);
22.
childGroup.ParentGroup = parentGroup;
23.
childGroup.DataControl = parentGroup.DataControl;
24.
}
25.
}));
26.
}
I'm assuming this bug is not "works as designed", because why would only the OUTERMOST\First level column group header show up (even if it isn't directly referenced by any columns).
Thanks,
Sam