web-dev-qa-db-fra.com

WPF DataGrid est très lent à rendre

J'ai essayé d'utiliser à la fois un DataGrid personnalisé ainsi que celui d'origine dans WPF. J'ai essayé de les remplir manuellement ainsi que par le biais de liaisons. Dans les deux cas, ils sont lents.

J'ai un scénario où l'utilisateur clique sur un bouton et un DataGrid apparaît avec les données appropriées. Actuellement, je suis en mode preuve de concept et j'utilise uniquement des exemples de données. J'ai un DataSet avec une table qui contient 10 lignes.

Si je n'attache aucune donnée au DataGrid lorsque je clique sur le bouton que le DataGrid vide affiche à peu près instantanément, un utilisateur ne peut pas percevoir de retard. Dès que j'ajoute 10 lignes de données, pour 6 colonnes, le délai est d'environ 2 secondes, très sensible à l'utilisateur.

J'ai même essayé de remplir des données vides, juste pour faire apparaître une grille vide et c'est tout aussi lent.

for (int i = 0; i < 10; i++)
    _dataGrid.Items.Add("");

Je mets une minuterie pour compter les ticks entre le moment où le bouton est cliqué et celui où tout le code est exécuté pour dessiner le DataGrid et il est d'environ 20 millisecondes, donc le code s'exécute très rapidement, mais sur l'écran se trouve le grand décalage . J'ai essayé un GridView et il s'affiche beaucoup plus rapidement à l'écran.

J'ai entendu divers rapports de dessin DataGrid lent avec des scénarios complexes et utilisant des milliers de lignes, mais c'est aussi simple que cela, 6 colonnes par 10 lignes remplies de données vides.

Pour l'affichage en lecture seule, GridView est-il une option tout aussi viable pour DataGrid?


Mettre à jour

Voici la création de mes colonnes.

                DataGridTextColumn column = new DataGridTextColumn();
                column.ColumnWidthChanged += new ColumnWidthChangedEventHandler(column_ColumnWidthChanged);

                column.Header = entity.GetPropertyValue("ColumnLabel");
                column.Binding = new Binding(entity.GetPropertyValue("Tag"));
                column.Width = new DataGridLength(entity.GetPropertyDouble("DisplaySize"));
                _dataGrid.Columns.Add(column);

C'est ainsi que je lie le DataSet avec 10 lignes.

                _dataGrid.ItemsSource = ds.Tables[0].DefaultView;
                _dataGrid.DataContext = ds.Tables[0];

Je ne sais pas ce que je peux faire différemment.

37
David Gunther

Avez-vous:

  • Activée VirtualizingStackPanel.VirtualizationMode pour une grille? sinon - essayez de régler.
  • Définissez VirtualizingStackPanel.IsVirtualizing = "true" pour DataGrid
  • Enveloppé d'une grille par un conteneur StackPanel? Si oui - essayez d'enlever.
  • Enveloppé une grille par un contrôle ScrollViewer externe? Si oui - essayez d'enlever.

Encore un point, pourriez-vous lier une collection d'éléments entiers à la fois au lieu d'ajouter chaque élément dans la grille. Collection d'articles?

36
sll

Un conseil général pour DataGrid problèmes de performances: j'ai eu un problème avec le DataGrid dans lequel il a fallu littéralement quelques secondes pour actualiser après le redimensionnement d'une fenêtre, le tri des colonnes, etc. et j'ai verrouillé l'interface utilisateur de la fenêtre pendant ce temps ( 1000 lignes, 5 colonnes).

Il s'agissait d'un problème (bug?) Avec les calculs de dimensionnement WPF. Je l'avais dans une grille avec le RowDefinitionHeight="Auto" qui obligeait le système de rendu à recalculer la taille du DataGrid au moment de l'exécution en mesurant la taille de chaque colonne et ligne, probablement en remplissant toute la grille (si je comprends bien). Il est censé gérer cela intelligemment, mais dans ce cas, ce n'était pas le cas.

Une vérification rapide pour voir s'il s'agit d'un problème connexe consiste à définir les propriétés Height et Width du DataGrid à une taille fixe pendant la durée du test, puis réessayez d'exécuter. Si vos performances sont restaurées, un correctif permanent peut figurer parmi ces options:

  • Modifiez les tailles des éléments contenant des valeurs relatives (*) ou fixes
  • Définissez MaxHeight et MaxWidth du DataGrid sur une valeur fixe supérieure à celle qu'il pourrait obtenir en utilisation normale
  • Essayez un autre type de conteneur avec une stratégie de redimensionnement différente (Grid, DockPanel, etc.)
25
TripleAntigen

n blog que j'ai trouvé sur Google m'a donné une sorte de solution. Comme l'a dit l'auteur, j'ai désactivé GroupStyle et le problème de vitesse de rendu a été résolu. Mais j'avais besoin d'un regroupement. L'auteur a dit

VirtualizingPanel.IsVirtualizingWhenGrouping

est ajouté à .NET 4.5. Je l'ai donc mis à vrai. Le rendu est désormais rapide avec le regroupement. Le problème est que ... le défilement est saccadé. Pas saccadé inacceptable, mais saccadé notable. J'ai eu un problème similaire lorsque j'ai essayé de créer un TreeView avec plus de 2000 nœuds étendus. Sans virtualisation, le rendu était lent mais le défilement était fluide. Avec la virtualisation, le rendu était rapide mais le défilement était saccadé.

Pourquoi ne pouvons-nous pas avoir les deux ...

12
Damn Vegetables

Dans mon cas, j'ai eu un problème avec DataGridCell ControlTemplate qui a ralenti le rendu.

Sachez que les vitesses de chargement relatives pour un grand ensemble de données sont très différentes pour l'utilisation de TextBlock (qui n'est pas du texte sélectionnable) ou TextBox en mode ReadOnly:

Temps de chargement 59 secondes:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellTextStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <TextBox IsReadOnly="True" Text="{Binding Mode=OneWay}"/> 
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Temps de chargement 21 secondes:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellTextStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                     <ContentPresenter Content="{Binding}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Temps de chargement 16 secondes:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellTextStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <TextBlock Text="{Binding}"></TextBlock>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
11
Evalds Urtans

Eh bien, en ajoutant un peu plus (je connais son sujet très ancien, mais ça aide quand même quelqu'un) ...

J'ai essayé

EnableColumnVirtualization="True" VirtualizingPanel.VirtualizationMode="Recycling"
EnableRowVirtualization="True" 

pour DataGrid (AutoGenerateColumns="True") liaison à DataTable.DefaultView () et aucun effet sur la vitesse, c'était toujours horrible pour la vitesse ainsi que pour la navigation entre les lignes. Ensuite, j'ai trouvé une solution pour définir la hauteur et la largeur fixes de DataGrid. De plus, je mets aussi

RowHeight="23" 
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"

Cela fait que ma page se remplit très rapidement ... Au lieu de 2 min, il ne faut désormais plus que 10 à 12 secondes.

J'espère que cela aide quelqu'un.

Remarque: j'utilise .Net 4.5

5
Nirav Raval

Pour moi, c'était:

<Setter Property='ScrollViewer.CanContentScroll' Value='False' />

J'ai supprimé cela du style et le rendu est devenu rapide.

2
waxingsatirical

J'avais de gros problèmes avec 1000 lignes, 5 colonnes où le temps de rendu prenait 7 à 10 secondes, mais la solution trouvée à https://www.elegant-software.net/2014/05/performance-of -the-wpf-datagrid.html a fait que la grille se charge instantanément!

<DataGrid
   EnableRowVirtualization="True"
   EnableColumnVirtualization="True">
2
Nick

J'ai une Surface Pro 3 sur laquelle ma grille de données, avec environ 200 lignes et 10 colonnes, était vraiment lente à défiler, saccadée et hésitante.

Je pensais que c'était le réseau, mais c'était en fait la carte graphique qui ne pouvait pas suivre - attendez - un effet d'ombre portée sur la grille de données elle-même, même si l'arrière-plan du contrôle était réglé sur une couleur unie.

J'ai commenté l'effet et c'était 4-5 fois plus rapide.

J'espère que cela t'aides.

1
user3515346

J'ai le même problème avec la grille de données liée, et je remarque que lors du premier chargement, il est rapide mais sur secand et ensuite il est lent. Donc, quand j'ajoute du code

DataGrid.ItemsSource = Nothing Puis TableAdapter.Fill(Mydataset.MyStoredProcedure,....) DataGrid.ItemsSource=Mydataset.MyStoredProcedure c'est devenu très RAPIDE

0
SLAVICA