Précédent   Forum des professionnels en informatique > Dotnet > Développement Windows > Windows Forms
Windows Forms Forum d'entraide sur le développement Windows Forms & Applications Windows. Avant de poster -> Articles Windows Forms
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 08/02/2012, 09h31   #1
Membre expérimenté
 
Homme Benjamin Fréson
Développeur .NET
Inscription : février 2009
Messages : 309
Détails du profil
Informations personnelles :
Nom : Homme Benjamin Fréson
Âge : 24
Localisation : Belgique

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

Informations forums :
Inscription : février 2009
Messages : 309
Points : 527
Points : 527
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 :
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
Type de fichier : jpg Aff_Rubs.jpg (197,4 Ko, 14 affichages)
Aeronia est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 10h56   #2
Membre habitué
 
Avatar de LeCygne
 
Raphael DAVID
Développeur .NET
Inscription : juin 2010
Messages : 62
Détails du profil
Informations personnelles :
Nom : Raphael DAVID
Localisation : France

Informations professionnelles :
Activité : Développeur .NET

Informations forums :
Inscription : juin 2010
Messages : 62
Points : 100
Points : 100
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
LeCygne est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 12h00   #3
Membre expérimenté
 
Homme Benjamin Fréson
Développeur .NET
Inscription : février 2009
Messages : 309
Détails du profil
Informations personnelles :
Nom : Homme Benjamin Fréson
Âge : 24
Localisation : Belgique

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

Informations forums :
Inscription : février 2009
Messages : 309
Points : 527
Points : 527
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.
Aeronia est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 15h08   #4
Membre habitué
 
Avatar de LeCygne
 
Raphael DAVID
Développeur .NET
Inscription : juin 2010
Messages : 62
Détails du profil
Informations personnelles :
Nom : Raphael DAVID
Localisation : France

Informations professionnelles :
Activité : Développeur .NET

Informations forums :
Inscription : juin 2010
Messages : 62
Points : 100
Points : 100
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 :
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();
            }
LeCygne est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 08/02/2012, 15h48   #5
Membre expérimenté
 
Homme Benjamin Fréson
Développeur .NET
Inscription : février 2009
Messages : 309
Détails du profil
Informations personnelles :
Nom : Homme Benjamin Fréson
Âge : 24
Localisation : Belgique

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

Informations forums :
Inscription : février 2009
Messages : 309
Points : 527
Points : 527
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 !
Aeronia est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 19h45   #6
Expert Confirmé Sénior
 
Avatar de Graffito
 
Inscription : janvier 2006
Messages : 4 717
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 4 717
Points : 5 029
Points : 5 029
Citation:
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
Graffito est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 09/02/2012, 12h42   #7
Membre expérimenté
 
Homme Benjamin Fréson
Développeur .NET
Inscription : février 2009
Messages : 309
Détails du profil
Informations personnelles :
Nom : Homme Benjamin Fréson
Âge : 24
Localisation : Belgique

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

Informations forums :
Inscription : février 2009
Messages : 309
Points : 527
Points : 527
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 :
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 :
1
2
3
4
 
RubriquesStylesHeader.Clear();
RubriquesStylesData.Clear();
RubriquesStylesTotal.Clear();
Et appel à la méthode suivante pour chaque DataGridView concerné
Code :
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 :
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 !
Aeronia est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 20h56.


 
 
 
 
Partenaires

Hébergement Web