Est-il possible de remplacer ItemsPresenter pour utiliser un StackPanel de virtualisation au lieu d'un panneau de pile standard ?
-
14-11-2019 - |
Question
Arrière-plan
J'ai un contrôle personnalisé qui hérite d'un TreeView et est modifié pour s'afficher dans un style de grille de données.Le problème que je vois concerne les performances lors de l’expansion de l’arborescence.Ceci est courant dans mes recherches avec Tree Views.Lors d'une inspection avec les outils de performances WPF, j'ai remarqué que la classe ItemsPresenter utilise un panneau de pile standard au lieu d'un panneau de pile de virtualisation.
Voici la section de code où le ScrollContentPresenter est utilisé (affiché dans l'image).
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CanContentScroll="{TemplateBinding CanContentScroll}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
Voici le modèle transmis.
<ControlTemplate TargetType="CommonControls:TreeListViewItem508">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border x:Name="item">
<Border Name="InnerBorder">
<Grid Style="{StaticResource GridBackgroundStyle}">
<Rectangle Visibility="Collapsed" Fill="#75FFFFFF" Name="UpperHighlight" />
</Grid>
</Border>
</Border>
<ItemsPresenter Grid.Row="1" Name="ItemsHost" />
</Grid>
</ControlTemplate>
Question
Est-il possible de forcer le présentateur d'éléments à utiliser un panneau de pile de virtualisation ?
Remarques
- J'ai déjà essayé d'envelopper ItemsPresenter dans un ScrollViewer mais cela donne des résultats indésirables (barres de défilement pour chaque ligne).
- J'ai codé en dur l'option CanContentScroll = true à titre de test car cela désactive la virtualisation lorsqu'elle est définie sur false.
- Ce contrôle est en production et utilisé à plusieurs endroits, je n'ai donc pas la possibilité de remplacer/réécrire/ou d'effectuer des modifications majeures à la conception à ce stade.Je cherche simplement à remplacer cette section si possible.
Toutes les suggestions ou options sont très appréciées.
Résolu:
J'ai modifié le style du modèle en l'ajoutant au style et cela a basculé les panneaux de pile vers la virtualisation.
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
La solution
essayer
<TreeView>
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
</TreeView>
ou
<TreeView VirtualizingStackPanel.IsVirtualizing="True">
Evriosuly remplace TreeView, avec votre nom de contrôle d'une arbreView.
espoir que cela aide
Paul
Autres conseils
Vous pouvez utiliser un VirtualizingStackPanel
, sachez cependant que la virtualisation d'un StackPanel ne se résume pas à la simple utilisation d'un VirtualizingStackPanel
Voici un exemple utilisant le code trouvé dans le lien posté ci-dessus qui répertorie les éléments nécessaires :
<ItemsControl ...
VirtualizingStackPanel.IsVirtualizing="True" <!-- this is needed -->
ScrollViewer.CanContentScroll="True" > <!-- this is needed -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel /> <!-- this is needed -->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border ...>
<ScrollViewer> <!-- this is needed -->
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>