Search code examples
c#.netwpftreeviewradtreeview

Improve WPF / telerik (Rad)TreeListView bad scrolling performance


I use a telerik RadTreeListView in my .NET 6 WPF application and experience very bad performance during scrolling.

Updates when using the scroll wheel can take 2 seconds and dragging the vertical scroll bar quickly results in lag spikes of <=5 seconds.

I have about 350 rows which are organized under a single top-level element. The view has 5 manually defined columns.

I profiled the performance and saw that virtually all the CPU time spent on the UI thread is used for layouting:

Profiling the problem

I tried enabling the virtualizing functionality by using the attributes EnableRowVirtualization, EnableColumnGroupsVirtualization, EnableColumnVirtualization.

What steps can I take to improve my scroll performance?

Edit: Here is the XAML of an example project that illustrates my problem.

<telerik:RadBusyIndicator Grid.Column="1"  Grid.Row="1"
                                              BusyContent="{Binding BusyReason}" IsBusy="{Binding BusyReason, Converter={StaticResource stringEmptyConverter}}" >
            <telerik:RadTreeListView  x:Name="treeView" ItemsSource="{Binding Pages, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" 
                                                 AutoGenerateColumns="False" AutoExpandItems="True"
                                                 SelectedItem="{Binding SelectedPage}"
                                                 PreviewMouseRightButtonDown="RadTreeListView_PreviewMouseRightButtonDown" IsDragDropEnabled="False"
                                      PreparedCellForEdit="treeView_PreparedCellForEdit"
                                      BeginningEdit="treeView_BeginningEdit"
                                      CanUserDeleteRows="False"
                                      EnableRowVirtualization="True"
                                      EnableColumnGroupsVirtualization="False"
                                      EnableColumnVirtualization="False"
                                      GroupRenderMode="Flat"
                                      IsPropertyChangedAggregationEnabled="False"
                                      >
                <telerik:RadTreeListView.ChildTableDefinitions>
                    <telerik:TreeListViewTableDefinition ItemsSource="{Binding ChildElements, Mode=TwoWay}"/>
                </telerik:RadTreeListView.ChildTableDefinitions>
                <telerik:RadTreeListView.Columns>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding Name, TargetNullValue=''}" Header="ID Name"
                                                Width="Auto" IsSortable="False" IsFilterable="False"/>
                    <telerik:GridViewComboBoxColumn  Header="ID" DataMemberBinding="{Binding Id, Mode=TwoWay}"
                                                IsSortable="False" IsFilterable="False"
                                                    ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type telerik:RadTreeListView}}, Path=DataContext.Ids}"
                                                     Width="100"
                                                    x:Name="columnWarnId"
                                                    IsLightweightModeEnabled="True"
                                                     EmptyText="not set"
                                                    >
                        <telerik:GridViewComboBoxColumn.EditorStyle>
                            <Style TargetType="telerik:RadComboBox" BasedOn="{StaticResource RadComboBoxStyle}">
                                <Setter Property="OpenDropDownOnFocus" Value="True"/>
                            </Style>
                        </telerik:GridViewComboBoxColumn.EditorStyle>
                        <telerik:GridViewComboBoxColumn.ItemTemplate>
                            <DataTemplate DataType="{x:Type dt:DataObject}">
                                <telerik:Label Content="{Binding IdName}"/>
                            </DataTemplate>
                        </telerik:GridViewComboBoxColumn.ItemTemplate>
                    </telerik:GridViewComboBoxColumn>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding Ca, TargetNullValue=''}" Header="Foobar"
                                                IsFilterable="False" 
                                                Width="65"
                                                x:Name="columnCa"
                                                />
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding HasChanged, TargetNullValue=''}" Header="*"
                                                IsFilterable="False"
                                                IsReadOnly="True">
                        <telerik:GridViewDataColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Visibility="{Binding HasChanged, Converter={helpers:BooleanToVisibilityConverter}}" Text="*"/>
                            </DataTemplate>
                        </telerik:GridViewDataColumn.CellTemplate>
                    </telerik:GridViewDataColumn>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding WarningsPresent, TargetNullValue=''}" Header="Warning"
                                                IsFilterable="False"
                                                IsReadOnly="True">
                        <telerik:GridViewDataColumn.CellTemplate>
                            <DataTemplate>
                                <Image HorizontalAlignment="Center" Visibility="{Binding WarningsPresent, Converter={helpers:BooleanToVisibilityConverter}}"                                    Source="pack://application:,,,/Resources/Images/icons8-fehler-48.png"
                                       Stretch="Uniform" 
                                       MaxHeight="24"/>
                            </DataTemplate>
                        </telerik:GridViewDataColumn.CellTemplate>
                    </telerik:GridViewDataColumn>
                </telerik:RadTreeListView.Columns>
            </telerik:RadTreeListView>
        </telerik:RadBusyIndicator>

Solution

  • The telerik Support offered feedback.

    The performance problem stems from the GridViewComboBoxColumn that - in my case - displays ~200 entries (the same for each row).

    It's a known issue that is not considered a bug by telerik since 2015.

    The root cause is that the underlying RadComboBox evaluates its contents even if it's not extended. When I removed the GridViewComboBoxColumn from my RadTreeView, performance jumped to acceptable levels in Debug mode and good performance in Release mode.

    The support page linked above suggests rewriting the collection for the ComboBox' items to a dictionary so that telerik-internal performance is improved.