2010-09-15 19 views
1

je grille dans une fenêtre WPF et un contrôle DataGrid intérieur:DataGrid dans un StackPanel conduit à OutOfMemoryException

<Grid> 
    <DataGrid ItemsSource="{Binding AllAuthors}" /> 
</Grid> 

AllAuthors est un ObservableCollection<Author> et Author une classe simple avec seulement quelques propriétés de chaîne. La collection est peuplée d'environ 40000 objets en code derrière. Le DataGrid s'ouvre assez rapidement (après 1 seconde) et la navigation dans le DataGrid se fait en douceur et rapidement. L'application a une charge de mémoire de 35 Mo.

Si je remplace le code ci-dessus par ...

<StackPanel> 
    <DataGrid ItemsSource="{Binding AllAuthors}" /> 
</StackPanel> 

... l'application fonctionne avec une charge de 100% du CPU et de la mémoire se développe sans interruption jusqu'à 1,5 Go tandis que l'application tente d'afficher le Grille de données. Enfin, je reçois un OutOfMemoryException.

Je suis débutant WPF et je me demande maintenant ce qui ne va pas ici. (J'utilise VS2010, .NET 4.0 et le contrôle DataGrid intégré de WPF 4.0)

Merci de votre aide à l'avance!

+0

Vous m'avez aidé à localiser mon problème: je gérais tout avec Task.run(), et quand je "mettais à jour" ma collection et élevais OnPropertyChanged(), l'outil plantait avec le même comportement (max RAM, outofMemoryException). Je cherchais des heures pour comprendre ce qui n'allait pas dans mon code C#, mais finalement, c'était dû au thread de l'interface utilisateur qui créait un énorme stackpanel! merci – Simon

Répondre

1

Tant que cela se trouve dans la grille, ce n'est pas un problème car probablement seulement quelques éléments sont réellement générés - ceux qui sont actuellement visibles. C'est ce qu'on appelle la virtualisation de l'interface utilisateur et elle est intégrée dans plusieurs ItemsControls dans WPF. Puisque le DataGrid est plutôt petit, il n'y a pas trop d'éléments réellement générés.

Cependant, lorsque vous le placez dans le StackPanel, vous pouvez avoir construit une mise en page dans laquelle StackPanel se développe jusqu'à la hauteur du DataGrid, alors que le DataGrid prend autant d'espace qu'il le juge nécessaire. Nous aurions besoin de voir le xaml complet pour voir si c'est le cas. De toute façon, si c'est le cas, maintenant il y a en fait beaucoup d'éléments "visibles" (c'est-à-dire tous). Et générer 40000 articles n'est évidemment pas une bonne idée.

Avez-vous comparé la propriété ActualHeight des deux DataGrids?

+0

Merci pour votre réponse! J'ai juste comparé ActualHeight pour la disposition Grid et StackPanel (pour seulement 500 éléments) et vous avez raison: Si le DataGrid est dans une Grille, la hauteur est seulement de 440, si elle est dans un StackPanel, elle dépasse 8800. I ' J'ai également défini 'EnableRowVirtualization = False' sur le DataGrid pour un test et dans ce cas j'ai le même problème de mémoire et de performance avec la disposition de la grille. Ce que je ne comprends pas, c'est pourquoi j'ai une charge de mémoire de plus de 1,5 Go. Les objets 'Author' ont une taille inférieure à 200 Byte, donc avec 40000 objets d'où viennent 1,5 Go? – Slauma

+0

Ceci provient de tous les visuels WPF générés pour chaque élément 'Author' basé sur ItemTemplate. – bitbonk

+0

OK, je vois. J'ai spécifié un 'Height' de 400 maintenant sur le DataGrid et maintenant il travaille également avec le StackPanel. Donc, si je conclus correctement, un 'Grid' restreint les contrôles à l'intérieur de la grille à la zone de la fenêtre visible tandis qu'un' StackPanel' peut se développer dans la zone invisible de la fenêtre en fonction des besoins des différents contrôles à l'intérieur. Est-ce correct? Quoi qu'il en soit, votre réponse a beaucoup aidé. Merci encore! – Slauma