IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Forms Discussion :

DataGridView - Lenteur de mise en forme


Sujet :

Windows Forms

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2009
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Février 2009
    Messages : 317
    Points : 560
    Points
    560
    Par défaut DataGridView - Lenteur de mise en forme
    Bonjour à tous,

    Bon alors je suis face à problème d'optimisation assez gênant.

    Je m'expliques :

    J'essaye d'appliquer une mise en forme à un DataGridView, le datagridview n'est pas rempli grâce à un binding.( Les rows sont ajoutées manuellement mais ce n'est pas ça le problème dans le cas présent)

    Le problème est que l'application de cette mise en forme, que je faisais à la base après l'ajout des mes données, via une méthode, est très lente !
    6 secondes pour 360 lignes ...

    Pour expliquer un peu comment cela fonctionne, j'affiche dans mon datagridview, une liste d'objet Rubrique. L'affichage est affiché comme suit :

    Une ligne correspondant au header (avec le nom de la rubrique)
    Plusieurs lignes correspondant aux données de la rubrique
    Une ligne correspondant aux totaux des données.

    A chaque rubrique est lié une mise en forme, dans laquelle on peut modifier le style du header, des données et du total.

    Ce qui donne un affichage comme sur l'image jointe.

    Voici la méthode que j'utilises pour appliquer les mises en forme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
          private void DataGridViewPreRapport_SetColoursAndFonts(DataGridView datagrid)
            {
                datagrid.SuspendLayout();
                int NombreColonnesAvantTotal = datagrid.Columns.Count-1;
                Rubrique CurrentRubrique = null;
                RubriqueLayout layout = new RubriqueLayout();
     
                foreach (DataGridViewRow row in datagrid.Rows)
                {
                    #region Init
                    Rubrique rub=null;
                    if (row.Tag != null)
                        rub = (Rubrique)row.Tag;
     
                    if (CurrentRubrique != rub)
                    {
                        CurrentRubrique = rub;
                        layout = new RubriqueLayout();
                        if (CurrentRubrique.UtilisationModeleLayout)
                        {
                            Modele_Layout_Rubrique modele = Dossier.GetModeleLayoutRubriqueByID(CurrentRubrique.RefModele);
                            if (modele != null && modele.Layout != null)
                                layout = modele.Layout;
                        }
                        else
                        {
                            if (CurrentRubrique.Layout != null)
                                layout = CurrentRubrique.Layout;
                        }
     
                    }
                    #endregion
                    #region Style
                    String Cell0 = row.Cells[0].Value.ToString();
                    String Cell1 = row.Cells[1].Value.ToString();
                    if (Cell0.Equals("") && Cell1.Equals("")) // Ligne total
                    {
                        row.DefaultCellStyle.Font = layout.FontTotal;
                        row.DefaultCellStyle.ForeColor = layout.ForeColorTotal;
                        row.DefaultCellStyle.BackColor = layout.BackgroundColorTotal;
                    }
                    else if (Cell0.Equals("") && !Cell1.Equals("")) // Ligne header
                    {
                        row.DefaultCellStyle.Font = layout.FontHeader;
                        row.DefaultCellStyle.ForeColor = layout.ForeColorHeader;
                        row.DefaultCellStyle.BackColor = layout.BackgroundColorHeader;
     
     
                    }
                    else //Ligne rubrique
                    {
                        row.DefaultCellStyle.Font = layout.FontData;
                        row.DefaultCellStyle.ForeColor = layout.ForeColorData;
                        row.DefaultCellStyle.BackColor = layout.BackgroundColorData;
                        row.Cells[NombreColonnesAvantTotal].Style.Font = new Font(layout.FontData, FontStyle.Bold);                    
                    }
                    #endregion
     
                }
                datagrid.ResumeLayout();
            }
    Alors pour avoir tester, le goulot d'étranglement se situe au niveau de la région Style, la région Init ne pose absolument aucun problème au point de vue performance.

    Donc à partir de là, étant un peu perdu, j'ai essayer de faire la mise en forme directement via un event du DataGridView (bien que je ne vois pas en quoi cela serait + rapide).

    J'ai donc utiliser ces events les un à la suite de l'autre :
    - RowPrePaint
    - RowPostPaint

    - CellPainting
    - CellFormating

    Mais rien n'y a fait, aucun gain de performance.

    Est ce le fait de modifier le DefaultCellStyle qui prend autant de temps ?

    Y'a t'il une autre manière de faire ?

    Merci de vos réactions éventuelles car la je suis relativement perdu ...
    Images attachées Images attachées  

  2. #2
    Membre habitué Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Points : 159
    Points
    159
    Par défaut
    Bonjour,

    Je n'ai jamais testé, mais à la lecture de votre code il me vient une idée : Pourquoi ne pas affecter un DefaultCellStyle à l'ensemble des lignes du DataGridView (DataGridView.RowsDefaultCellStyle), et un DefaultCellStyle uniquement aux lignes "total" et "header" ?
    Cela ferait bien moin d'affectations de style. Voici un lien vers une page microsoft où est expliqué l'ordre dans lequel les styles sont appliqués : http://msdn.microsoft.com/fr-fr/library/1yef90x0.aspx

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2009
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Février 2009
    Messages : 317
    Points : 560
    Points
    560
    Par défaut
    Bonjour,
    malheureusement je ne peux pas car chaque rubrique a une mise en page différente.
    Comme on peut le voir sur l image, chaque rubrique est affichée à la suite l'une de l'autre.

  4. #4
    Membre habitué Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Points : 159
    Points
    159
    Par défaut
    Selon un article de Microsoft (http://msdn.microsoft.com/fr-fr/libr...cellstyle.aspx) il y a instanciacion automatique d'un nouveau DataGridViewCellStyle à chaque lecture de celui-ci. Probablement 360 fois dans votre cas. Peut être qu'en préparant ces styles à l'avance, vous pourriez controler (et limiter) le nombre d'instanciation de style. Y a-t-il une amélioration en tournant le code de la manière suivante ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
            private void DataGridViewPreRapport_SetColoursAndFonts(DataGridView datagrid)
                {
                datagrid.SuspendLayout();
                int NombreColonnesAvantTotal = datagrid.Columns.Count - 1;
                Rubrique CurrentRubrique = null;
                RubriqueLayout layout = new RubriqueLayout();
     
                DataGridViewCellStyle totalStyle;
                DataGridViewCellStyle headerStyle;
                DataGridViewCellStyle rubriqueStyle;
     
                foreach (DataGridViewRow row in datagrid.Rows)
                    {
                    #region Init
                    Rubrique rub = null;
                    if (row.Tag != null)
                        rub = (Rubrique)row.Tag;
     
                    if (CurrentRubrique != rub)
                        {
                        CurrentRubrique = rub;
                        layout = new RubriqueLayout();
                        if (CurrentRubrique.UtilisationModeleLayout)
                            {
                            Modele_Layout_Rubrique modele = Dossier.GetModeleLayoutRubriqueByID(CurrentRubrique.RefModele);
                            if (modele != null && modele.Layout != null)
                                layout = modele.Layout;
                            }
                        else
                            {
                            if (CurrentRubrique.Layout != null)
                                layout = CurrentRubrique.Layout;
                            }
     
                        #region Preparation des styles pour la rubrique
     
                        totalStyle = new DataGridViewCellStyle();
                        totalStyle.Font = layout.FontTotal;
                        totalStyle.ForeColor = layout.ForeColorTotal;
                        totalStyle.BackColor = layout.BackgroundColorTotal;
     
                        headerStyle = new DataGridViewCellStyle();
                        headerStyle.Font = layout.FontHeader;
                        headerStyle.ForeColor = layout.ForeColorHeader;
                        headerStyle.BackColor = layout.BackgroundColorHeader;
     
                        rubriqueStyle = new DataGridViewCellStyle();
                        rubriqueStyle.Font = layout.FontData;
                        rubriqueStyle.ForeColor = layout.ForeColorData;
                        rubriqueStyle.BackColor = layout.BackgroundColorData;
     
                        #endregion Preparation des styles pour la rubrique
     
                        }
                    #endregion
     
                    #region Style
     
     
                    String Cell0 = row.Cells[0].Value.ToString();
                    String Cell1 = row.Cells[1].Value.ToString();
                    if (Cell0.Equals("")) // Ligne total ou Ligne header
                        {
                        if (Cell1.Equals(""))// Ligne total
                            {
                            row.DefaultCellStyle = totalStyle;
                            }
                        else //Ligne header
                            {
                            row.DefaultCellStyle = headerStyle;
                            }
                        }
                    else //Ligne rubrique
                        {
                        row.DefaultCellStyle = rubriqueStyle;
                        row.Cells[NombreColonnesAvantTotal].Style.Font = new Font(layout.FontData, FontStyle.Bold);
                        }
                    #endregion
     
                    }
                datagrid.ResumeLayout();
                }

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2009
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Février 2009
    Messages : 317
    Points : 560
    Points
    560
    Par défaut
    Alors je viens de tester ta solution et j'ai effectivement un gain de temps fortement appréciable.
    Je passes de 6 secondes à 2.7, ce qui est loin d'être négligeable
    Donc déjà un grand merci à toi pour cette solution.

    Mais je trouves que cela reste encore très long pour 300 lignes :/

    Je me demandes ce qui continue à prendre encore autant de temps !

  6. #6
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Mais je trouves que cela reste encore très long pour 300 lignes :/
    C'est aussi mon avis.
    Je pense qu'on gagnerait nettement en créant les différents styles au départ et en les affectant aux cellules sur l'event CellFormatting.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2009
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Février 2009
    Messages : 317
    Points : 560
    Points
    560
    Par défaut
    J'ai testé ta solution graffito et en effet cela semble bien fonctionner

    J'ai utiliser 3 Dictionary pour stocker mes différents styles. J'ai été contraint d'en utiliser 3 quoi car pour chaque rubrique, j'ai 3 styles différents a chaque fois, et si je les mettais tous dans un même Dictionary, impossible de savoir quel est le style header, total ou data ...

    Pour ceux que ça intéresse voici, en simplifié ce qui est fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Dictionary<Guid, DataGridViewCellStyle> RubriquesStylesHeader = new Dictionary<Guid, DataGridViewCellStyle>();
            Dictionary<Guid, DataGridViewCellStyle> RubriquesStylesData = new Dictionary<Guid, DataGridViewCellStyle>();
            Dictionary<Guid, DataGridViewCellStyle> RubriquesStylesTotal = new Dictionary<Guid, DataGridViewCellStyle>();
    Lors de la modification de mes modèles / affectations d'un modèle à une rubrique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    RubriquesStylesHeader.Clear();
    RubriquesStylesData.Clear();
    RubriquesStylesTotal.Clear();
    Et appel à la méthode suivante pour chaque DataGridView concerné
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    private void TabPagesPreRapport_SetColoursAndFonts(DataGridView datagrid)
            {
                datagrid.SuspendLayout();
                int NombreColonnesAvantTotal = datagrid.Columns.Count - 1;
                Rubrique CurrentRubrique = null;
                RubriqueLayout layout = new RubriqueLayout();
     
                DataGridViewCellStyle totalStyle = datagrid.DefaultCellStyle.Clone();
                DataGridViewCellStyle headerStyle = datagrid.DefaultCellStyle.Clone();
                DataGridViewCellStyle dataStyle = datagrid.DefaultCellStyle.Clone();
     
     
                foreach (DataGridViewRow row in datagrid.Rows)
                {
                    #region Init
                    Rubrique rub = null;
                    if (row.Tag != null)
                        rub = (Rubrique)row.Tag;
     
                    if (CurrentRubrique != rub)
                    {
                        CurrentRubrique = rub;
                        layout = new RubriqueLayout();
                        if (CurrentRubrique.UtilisationModeleLayout)
                        {
                            Modele_Layout_Rubrique modele = Dossier.GetModeleLayoutRubriqueByID(CurrentRubrique.RefModele);
                            if (modele != null && modele.Layout != null)
                                layout = modele.Layout;
                        }
                        else
                        {
                            if (CurrentRubrique.Layout != null)
                                layout = CurrentRubrique.Layout;
                        }
     
                        #region Preparation des styles pour la rubrique
                        totalStyle = datagrid.DefaultCellStyle.Clone();
                        totalStyle.Font = layout.FontTotal;
                        totalStyle.ForeColor = layout.ForeColorTotal;
                        totalStyle.BackColor = layout.BackgroundColorTotal;
                        RubriquesStylesTotal.Add(CurrentRubrique.ID, totalStyle);
     
                        headerStyle = datagrid.DefaultCellStyle.Clone();
                        headerStyle.Font = layout.FontHeader;
                        headerStyle.ForeColor = layout.ForeColorHeader;
                        headerStyle.BackColor = layout.BackgroundColorHeader;
                        RubriquesStylesHeader.Add(CurrentRubrique.ID, headerStyle);
     
                        dataStyle = datagrid.DefaultCellStyle.Clone();
                        dataStyle.Font = layout.FontData;
                        dataStyle.ForeColor = layout.ForeColorData;
                        dataStyle.BackColor = layout.BackgroundColorData;
                        RubriquesStylesData.Add(CurrentRubrique.ID, dataStyle);
     
                        #endregion Preparation des styles pour la rubrique
     
                    }
                    #endregion
     
                }
                datagrid.ResumeLayout();
            }
    Et dans l'event CellFormatting des mes DataGridView :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
       private void dataGridViewPreRapport_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
            {
                DataGridView data = (DataGridView)sender;
                DataGridViewRow row = data.Rows[e.RowIndex];
                Rubrique CurrentRubrique = null;
                if (row.Tag != null)
                    CurrentRubrique = (Rubrique)row.Tag;
                if (CurrentRubrique == null)
                    return;
     
                Guid id = CurrentRubrique.ID;
     
                String Cell0 = row.Cells[0].Value.ToString();
                String Cell1 = row.Cells[1].Value.ToString();
                DataGridViewCellStyle style = data.DefaultCellStyle.Clone();
     
                if (Cell0.Equals("") && Cell1.Equals("")) // Ligne total
                {
                    var res = RubriquesStylesTotal.Where(ru => ru.Key == id);
     
                    if (res.Count() > 0)
                    {
                        style = res.First().Value;
     
                    }
     
                    e.CellStyle = style;
                }
                else if (Cell0.Equals("") && !Cell1.Equals("")) // Ligne header
                {
                    var res = RubriquesStylesHeader.Where(ru => ru.Key == id);
                    if (res.Count() > 0)
                    {
                        style = res.First().Value;
                    }
                    e.CellStyle = style;
     
                }
                else //Ligne data
                {
                    var res = RubriquesStylesData.Where(ru => ru.Key == id);
                    if (res.Count() > 0)
                    {
                        style = res.First().Value;
                    }
                    e.CellStyle = style;
     
     
                }
     
            }
    Alors je pourrais au lieu de vider mes Dictionary, chercher si mon DataGridViewCellStyle lié à ma rubrique y est déjà présente et la modifier
    Mais je ne sais pas si je vais vraiment y gagner au niveau performance ?

    Avez vous des remarques sur ma manière de faire ?

    Merci d'avance !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lenteur mise en forme par VBA
    Par Glherbier dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 02/11/2010, 11h24
  2. Mise en forme DataGridView
    Par gls80 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 10/09/2010, 10h04
  3. Mise en forme DataGridView
    Par jemmass dans le forum Windows Forms
    Réponses: 0
    Dernier message: 09/10/2009, 17h47
  4. Mise en forme d'une DataGridview
    Par rdh123 dans le forum C#
    Réponses: 1
    Dernier message: 14/11/2008, 10h41
  5. [CR9] lenteur mise en forme des couleurs dans expert diagram
    Par cdu dans le forum SAP Crystal Reports
    Réponses: 6
    Dernier message: 20/04/2005, 08h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo