WPF DataGrid virtualisation avec regroupement
j'utilise le WPF DataGrid de CodePlex et je dois obtenir la virtualisation pour travailler avec le groupement.
cette question est sur le sujet et pointe à un MSDN exemple mais il ne couvre ListControls avec simple (i.e. simple "colonne") Dataemplates.
regroupement et virtualisation semble être un cas d'utilisation assez courant pour une grille. Est-il standard/recommandé/moyen simple d'obtenir ce que ça va?
4 réponses
je me rends compte que je suis en retard à la fête ici... mais j'ai rencontré ce problème récemment (en utilisant le DataGrid intégré dans .NET 4). Malheureusement, il n'y a toujours pas de virtualisation des lignes une fois que le groupement est utilisé sur le DataGrid... mais a j'ai trouvé un tour d'amélioration de performance très habile que j'espère que quelqu'un d'autre trouvera utile ainsi.
en supposant que vous utilisez un ItemsPresenter dans un expander du modèle de votre GroupItem et par défaut votre expander n'est pas expanded, puis essayez simplement de lier la visibilité de votre ItemsPresenter à la propriété IsEnabled de L'expandeur avec le BooleanToVisibilityConverter par défaut:
<BooleanToVisibilityConverter x:Key="bool2vis" />
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp">
<ItemsPresenter Visibility="{Binding ElementName=exp, Path=IsExpanded, Converter={StaticResource bool2vis}}" />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
si vous rencontrez un problème où votre DataGrid prend beaucoup de temps à se charger (parce qu'il s'agit essentiellement de dessiner tous les enregistrements dans votre datagrid, même s'il est dans un expandeur effondré)... ensuite, l'utilisation du code ci-dessus fera que le datagrid ne dessinera pas vos enregistrements jusqu'à ce que vous développiez un groupe, et ensuite, il ne tirera que les enregistrements pour ce groupe particulier.
le côté négatif est que cela n'aide que si vos expanders sont effondrés par défaut, et encore les lignes ne sont pas virtualisées (si vous avez 100 articles dans un groupe étendu, mais seulement 20 s'ajustent sur l'écran, tous les 100 seront dessinés au moment où vous avez étendu le groupe).
le bon côté est que vous avez essentiellement mis en œuvre le chargement paresseux de vos enregistrements DataGrid, donc vous n'effectuez pas le travail de dessin jusqu'à ce que vous avez réellement besoin de voir les articles (vous choisissez d'élargir le groupe). Pour mon produit, mon en-tête de groupe avait des boutons intégrés pour effectuer des opérations sur tous les éléments au sein de son groupe, de sorte que le plus souvent l'utilisateur n'a jamais élargi un groupe à moins qu'ils aient besoin d'effectuer une opération sur un élément individuel au sein d'un groupe.
*une chose à noter Si vous utilisez cette astuce est que vous devriez probablement mettre quelques largeurs explicites ou des largeurs minimales à vos en-têtes de colonne (parce que le les articles ne sont pas dessinés lorsque la DataGrid charge pour la première fois, de sorte que les en-têtes de colonne ne peuvent pas être autosize pour s'adapter à l'article le plus grand).
avec un peu de chance, la vraie virtualisation sera implémentée dans un futur service pack, mais si ce n'est pas le cas, j'espère que cela aidera quelqu'un d'autre!
mise à Jour
Il semble que ce problème sera résolu .NET 4.5 avec une nouvelle propriété attachée VirtualizingPanel.Isvirtualizing whengrouping .
il y a une nouvelle propriété attachée à framework 4.5 VirtualizingPanel.IsVirtualizingWhenGrouping , qui permet d'activer la virtualisation lors du regroupement.
<DataGrid EnableColumnVirtualization="True" EnableRowVirtualization="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True">
il n'y a pas de fonctionnalité intégrée qui vous permette d'activer la virtualisation de L'UI lorsque le groupement est activé dans un ListView ou un DataGrid, si vous y pensez une seconde, cela a aussi du sens. Comment est le DataGrid pour grouper les éléments qui n'existent pas. Pour appliquer le regroupement, le contrôle devrait charger l'ensemble de la collection, ce qui irait à l'encontre du but de la virtualisation. Le mieux que vous pouvez probablement faire est de fournir une sorte de virtualisation dans votre viewmodel (l'objet que vous liez à nouveau) dans que vous fournissez seulement les données qui est actuellement nécessaire plus une sorte de données génériques sur la quantité de données qui existe et puis truquer la vue vous-même.
avec le groupement il pourrait aller quelque chose comme ceci: quand le groupement est activé initialement tous les groupes seraient effondrés. Ainsi, votre modèle de vue n'aurait à fournir qu'un élément pour chaque groupe qu'il existe. Juste pour s'assurer que l'affichage contient capter tous les groupes. Dès que l'utilisateur étend un groupe le ViewModel remplirait dynamiquement les articles pour ce groupe. C'est un moyen très simple et basique de virtulisation et pas optimal, mais il pourrait être un bon point de départ. C'est juste pour illistrate l'approche.
comme vous l'avez dit, activer le regroupement va désactiver la virtualisation de L'UI.
je ne pense pas que vous trouverez un moyen facile de résoudre ce problème. Je vous recommande de vérifier l'une des Datagrades WPF disponibles comme la XCeeed qui pourrait avoir cette fonctionnalité intégrée dans leur contrôle.