2009-01-22 7 views
6

J'essaie de créer un type de contrôle qui affichera un grand nombre de vignettes, comme celle utilisée par Picasa.Remplir un FlowLayoutPanel avec un grand nombre de contrôles et peindre des miniatures à la demande

Ceci est ma conception:

J'ai un FlowLayoutPanel qui est rempli avec beaucoup de UserControl objets, par exemple 4000. Chaque délégué UserControl reçoit un délégué pour l'événement Paint. Lorsque l'événement Paint est appelé, il vérifie un cache mémoire pour la vignette et si l'image n'est pas dans le cache, il l'extrait du disque.

J'ai deux problèmes que je suis en train de résoudre:

  1. Il semble que WinForms déclenchera un événement Paint même si le UserControl n'est pas en vue. Seulement une dizaine de contrôles sont en fait visibles, le reste ne l'est pas (le FlowLayoutPanel.AutoScroll est défini sur true). En conséquence, il essaie de récupérer des vignettes pour toutes les images et cela prend beaucoup de temps. Ajouter les objets UserControl au FlowLayoutPanel prend un peu de temps, environ 2-3 secondes. Je peux vivre avec elle, mais je me demande s'il y a une meilleure façon de le faire que:

    UserControl[] boxes = new UserControl[N]; 
    // populate array 
    panel.SuspendLayout(); 
    panel.Controls.AddRange(boxes); 
    panel.ResumeLayout(); 
    
+1

Avoir le même problème. Je travaille avec des "contrats" qui peuvent avoir x lignes (x contrôles dans le fl-panel) et je vois aussi le temps long pour remplir le panneau avec toutes les commandes. 2-3 secondes pour 200 articles (pas même 4000 comme dans votre cas). Ill "fav" cette question à coup sûr. ;) – Stefan

+0

Im allso utilisant suspendlayout/resumelayout et visible vrai/faux lors du remplissage des objets. – Stefan

Répondre

3

je ne voudrais pas ajouter que de nombreux contrôles utilisateur. Au contraire, j'aurais une série de structures de données qui stocke des informations sur la miniature à utiliser, le positionnement, etc, etc, puis gérer le rendu de chaque miniature requise.

Bien sûr, vous ne calculiez que ce dont vous aviez besoin, en vérifiant les arguments de l'événement paint dans votre contrôle et en affichant les vignettes qui sont visibles et qui nécessitent un rendu.

+0

Ça va devenir un peu trop complexe pour ce dont j'ai besoin. Ajouter les contrôles n'est pas vraiment un problème. Des idées comment résoudre (1)? –

+1

Il existe un plafond global sur le nombre de poignées de fenêtre que votre application peut avoir. Chaque contrôle utilisateur génère au moins un descripteur (plus si vous avez d'autres contrôles à l'intérieur) et votre application va planter si vous dépassez le nombre de poignées autorisé. – Nick

+0

Il y a une limite d'environ 10K poignées que le système d'exploitation permettra ainsi, comme dans mon cas où j'ai un navigateur avec des icônes potentiellement 200K-300K dans une application de navigateur, la pagination est la seule option. –

1

Aha! J'ai trouvé quelque chose.

Lorsque le UserControl n'est pas visible et qu'il reçoit un événement Paint, e.ClipRectangle.IsEmpty est true!

5

Pour améliorer la vitesse de remplissage du FlowLayoutPanel avec vos commandes utilisateur, désactivez la mise à jour de la mise en page pendant que vous ajoutez les contrôles.

Immédiatement avant votre boucle, appelez SuspendLayout() puis à la fin appel ResumeLayout(). Veillez à utiliser un try-finally pour garantir l'exécution de ResumeLayout() même si une exception se produit.

Questions connexes