31 votes

Performances des Datagrids WPF

Je travaille avec la grille de données WPF Toolkit et le défilement est extrêmement lent en ce moment. La grille comporte 84 colonnes et 805 lignes. (Y compris 3 colonnes fixes et l'en-tête est fixe.) Le défilement horizontal et vertical est extrêmement lent. La virtualisation est activée et j'ai activé la virtualisation des colonnes et des lignes de manière explicite dans le xaml. Y a-t-il quelque chose à surveiller qui puisse vraiment affecter les performances, comme les méthodes de liaison, ou le xaml qui se trouve dans chaque modèle de cellule ?

Il convient de noter que j'ajoute dynamiquement les colonnes lors de la création de la grille de données. Cela peut-il avoir un effet ? (Je crée aussi dynamiquement le modèle de cellule en même temps pour que mes liaisons soient bien définies).

Vous trouverez ci-dessous le code du modèle pour la plupart des cellules qui sont générées. Pour les colonnes que je dois ajouter dynamiquement (c'est-à-dire la plupart d'entre elles), je boucle dans ma liste et j'ajoute les colonnes à l'aide de la méthode AddColumn, puis je construis dynamiquement le modèle pour que les instructions de liaison indexent correctement le bon élément de la collection pour cette colonne. Le modèle n'est pas trop complexe, juste deux TextBlocks, mais je lie quatre propriétés différentes sur chacun. Il semble que j'ai pu obtenir un peu plus de performances en modifiant les liaisons avec OneWay :

 private void AddColumn(string s, int index)
    {
        DataGridTemplateColumn column = new DataGridTemplateColumn();
        column.Header = s;
        //Set template for inner cell's two rectangles
        column.CellTemplate = CreateFactViewModelTemplate(index);
        //Set Style for header, ie rotate 90 degrees
        column.HeaderStyle = (Style)dgMatrix.Resources["HeaderRotateStyle"];
        column.Width = DataGridLength.Auto;
        dgMatrix.Columns.Add(column);
    }

    //this method builds the template for each column in order to properly bind the rectangles to their color
    private static DataTemplate CreateFactViewModelTemplate(int index)
    {
        string xamlTemplateFormat =
            @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
            xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
            <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column=""0"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].LeftForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].LeftColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].LeftScore,Mode=OneWay}"" />
            <TextBlock Grid.Column=""1"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].RightForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].RightColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].RightScore,Mode=OneWay}"" />
            </Grid>
            </DataTemplate>";

        string xamlTemplate = xamlTemplateFormat.Replace("~Index~", index.ToString());

        return (DataTemplate)XamlReader.Parse(xamlTemplate);
    }

20voto

Tobias Hertkorn Points 1909

Comme je ne peux pas voir votre code source, il est assez difficile de vous aider. D'autant plus que les performances d'une application WPF sont influencées par de nombreux facteurs. Pour quelques conseils sur les points à surveiller, voir Optimisation des performances des applications WPF . Et oui, le type de xaml utilisé dans chaque cellule a une grande importance. En effet, les problèmes de performances se résument généralement à un "trop grand nombre d'éléments". Saviez-vous qu'une TextBox est composée de 30 éléments individuels ? Je vous recommande d'utiliser le Outils de profilage des performances pour WPF pour en savoir plus sur votre problème spécifique. Essayez de minimiser la quantité d'éléments que vous utilisez (par exemple, en passant de TextBox à TextBlock le cas échéant).

Vous devez également vérifier si les problèmes de performances existent sur tous les PC sur lesquels vous essayez l'application. Peut-être que le PC que vous utilisez force WPF à utiliser un rendu logiciel. Ou bien utilisez-vous des BitmapEffects ?

Edit :
En regardant votre code, je vous suggère de changer

column.Width = DataGridLength.Auto;

à une largeur fixe raisonnable, puisque la grille de données ne doit pas recalculer la largeur dynamiquement chaque fois que quelque chose change (comme l'ajout de lignes, ou même le défilement).

12voto

TripleAntigen Points 753

Une astuce générale pour les problèmes de performance des DataGrid : J'ai eu un problème avec le DataGrid qui prenait littéralement des secondes pour se rafraîchir après un redimensionnement de la fenêtre, un tri de colonne, etc. et qui verrouillait 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 taille de WPF. Je l'avais placé dans une grille avec RowDefinition Height="Auto", ce qui faisait que le système de rendu essayait de recalculer la taille de la grille de données au moment de l'exécution en mesurant la taille de chaque colonne et de chaque ligne, vraisemblablement en remplissant toute la grille (si j'ai bien compris). Le système est censé gérer cela intelligemment, mais dans ce cas, ce n'est 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 de hauteur et de largeur de la grille de données à une taille fixe pour la durée du test, puis à réessayer. Si vos performances sont rétablies, il se peut qu'une solution permanente figure parmi ces options :

  • Modifier les tailles des éléments contenus pour qu'elles soient relatives (*) ou valeurs fixes
  • Définissez MaxHeight et MaxWidth de la grille de données à une valeur fixe plus grande que ce qu'elle pourrait obtenir dans une utilisation normale
  • Essayez un autre type de conteneur avec une stratégie de redimensionnement différente (Grid, DockPanel, etc.).

2voto

Dans l'un de mes projets, le paramètre de style de grille suivant causait un problème de performance majeur :

 <Style  TargetType='{x:Type controls:DataGrid}'>
    <Setter Property='ScrollViewer.CanContentScroll' Value='False' />
    ...

Lorsque j'ai supprimé le paramètre ScrollViewer.CanContentScroll, le problème de performance a disparu.

1voto

J'ai eu un cas où mon objet sous-jacent avait une propriété avec setter seulement. La même propriété était accessible en implémentant ITypedList dans la collection et via TypeDescriptionProvider/ICustomTypeDescriptor sur les objets individuels. La suppression de la propriété ou l'ajout d'un getter a permis de résoudre les problèmes de performance.

1voto

Vibes Points 31

Une chose que je suggérerais dans de tels scénarios est de regarder comment vous avez appliqué le style et quel est le style de chaque cellule. Si l'arbre visuel est complexe, le style appliqué a tendance à dégrader les performances.

Vous pouvez également essayer l'option de défilement différé de la dernière version de WPF Datagrid.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X