Extremely bad performance when using a GroupStyle

Jul 14, 2009 at 9:07 PM

If I add a GroupDescription without setting a GroupStyle in my grid (6800 items), it groups everything together instantly. But then when I add a simple style to show a header or maybe an expander, performance is so bad it can take up to a few minutes to render, and then even when it does I can't scroll at all horizontally. Is this some virtualization issue where I just won't be able to show any header for the groups or is there something wrong with my style?

<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">
                    <Expander x:Name="expander" IsExpanded="True" Style="{x:Null}"">
                        <Expander.Header>
                            <DockPanel TextBlock.Foreground="Black" TextBlock.FontWeight="Normal" >
                                <TextBlock Text="{Binding Path=Name}" Margin="5,0,0,0" />
                                <TextBlock Text=" - (" />
                                <TextBlock Text="{Binding Path=ItemCount}" FontWeight="Bold" Foreground="#005074"/>
                                <TextBlock Text=")" />
                            </DockPanel>
                        </Expander.Header>
                        <ItemsPresenter />                        
                    </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <GroupStyle x:Key="gs_Default" ContainerStyle="{StaticResource GroupHeaderStyle}">
        <GroupStyle.Panel>
            <ItemsPanelTemplate>
                <toolkit:DataGridRowsPresenter/>
            </ItemsPanelTemplate>
        </GroupStyle.Panel>
    </GroupStyle>

Jul 15, 2009 at 12:26 AM

I had this problem with Grouping in a ListBox. The creation of the list was very slow. I narrowed down the problem to my DataTemplate. Are you using a DataTemplate to define each item in your collection? Optimizing my data template worked for me. I had some custom controls in my data template, replacing them with styles and brushes was one optimization. I would love to learn how to further optimize this interface.

Jul 15, 2009 at 2:07 PM

No DataTemplate's. Just a custom Template for the row:

<ControlTemplate x:Key="DataGridRowControlTemplate" TargetType="{x:Type Controls:DataGridRow}">
        <Grid x:Name="LayoutRoot" Margin="0,0,0,-1" MouseLeftButtonDown="DataGridRow_MouseDown">
            <Border x:Name="DGR_Border" BorderBrush="Transparent" Margin="0,0,-2,0" Background="Transparent" BorderThickness="1" CornerRadius="5" SnapsToDevicePixels="True">
                <Border x:Name="DGR_InnerBorder" BorderBrush="Transparent" Background="Transparent" BorderThickness="1" CornerRadius="5" SnapsToDevicePixels="True">
                    <toolkit:SelectiveScrollingGrid x:Name="DGR_SelectiveScrollingGrid">
                        <toolkit:SelectiveScrollingGrid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </toolkit:SelectiveScrollingGrid.ColumnDefinitions>

                        <toolkit:SelectiveScrollingGrid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </toolkit:SelectiveScrollingGrid.RowDefinitions>

                        <toolkit:DataGridCellsPresenter Grid.Column="1" x:Name="DGR_CellsPresenter" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        <toolkit:DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" Visibility="{TemplateBinding DetailsVisibility}" toolkit:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding Path=AreRowDetailsFrozen, Converter={x:Static Controls:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static Controls:SelectiveScrollingOrientation.Vertical}, RelativeSource={RelativeSource AncestorType={x:Type Controls:DataGrid}}}" />
                        <toolkit:DataGridRowHeader Grid.Column="2" Grid.RowSpan="2" toolkit:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding Path=HeadersVisibility, Converter={x:Static Controls:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static Controls:DataGridHeadersVisibility.Row}, RelativeSource={RelativeSource AncestorType={x:Type Controls:DataGrid}}}"/>
                    </toolkit:SelectiveScrollingGrid>
                </Border>
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="True" />
                    <Condition Property="IsSelected" Value="False" />
                </MultiTrigger.Conditions>
                <Setter TargetName="DGR_Border" Property="BorderBrush" Value="{StaticResource InactiveOuterBorderBrush}" />
                <Setter TargetName="DGR_InnerBorder" Property="BorderBrush" Value="{StaticResource InactiveInnerBorderBrush}" />
                <Setter TargetName="DGR_Border" Property="Background" Value="{StaticResource InactiveSelectedBackgroundBrush}" />
            </MultiTrigger>
            <Trigger Property="IsSelected" Value="True">
                <Setter TargetName="DGR_Border" Property="BorderBrush" Value="{StaticResource OuterBorderBrush}" />
                <Setter TargetName="DGR_InnerBorder" Property="BorderBrush" Value="{StaticResource InnerBorderBrush}" />
                <Setter TargetName="DGR_Border" Property="Background" Value="{StaticResource SelectedBackgroundBrush}" />
            </Trigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="ItemsControl.AlternationIndex" Value="1" />
                    <Condition Property="IsSelected" Value="False" />
                    <Condition Property="IsMouseOver" Value="False" />
                </MultiTrigger.Conditions>
                <Setter TargetName="DGR_Border" Property="Background" Value="{StaticResource AlternatingBackgroundBrush}" />
                <Setter TargetName="DGR_InnerBorder" Property="BorderBrush" Value="{StaticResource AlternatingBorderBrush}" />
            </MultiTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

Jul 15, 2009 at 6:42 PM

Virtualization is turned off as soon as you enable grouping, which is probably the reason why you are seeing the awful performance.

Jul 15, 2009 at 7:05 PM

That was what I was afraid of. Is there plans to have this functionality in the dev10 version or another release between now and then? As a workaround I just collapsed all the groups by default, performance is then acceptable for smaller groups of items.

Jul 16, 2009 at 1:45 PM

I haven't seen any changes to the grouping/virtualization in the .NET 4.0 beta 1, unfortunately.