[new:20/5/2010] Êtes-vous plutôt Hard ou Soft ? Ok, c’est trop personnel comme question. Mais si on la pose à une ListBox immédiatement on se sent plus à l’aise pour répondre…
La ListBox Hard et la ListBox Smooth
Ce n’est pas une fable de La Fontaine, mais une affaire de visuel sous Silverlight et WPF.
Pour la listbox d’ailleurs on parlera plutôt de hard et smooth. Une ListBox “soft”, ça ferait trop montres molles de Dali ! Pour être d’ailleurs plus pointilleux, on opposerait Smooth à Rugged, Scratchy ou ici plutôt à Rough qu’à Hard. Mais heureusement pour certains on n’est pas là pour faire un cours d’anglais :-)
Regardez attentivement les deux ListBox de l’exemple live ci-dessous… Vous ne voyez vraiment pas de différence ? Normal, il n’y en a pas, c’était un piège :-) En fait si, bien sûr, il y a une différence, mais elle ne saute pas aux yeux, il faut manipuler les ascenseurs pour s’en rendre compte. Allez-y…
[silverlight:source=/SLSamples/HardSmooth/SLSmooth.xap;width=565;height=335]
Smooth Scrolling vs Rough Scrolling
Ce coup-ci vous avez vu ? La ListBox de gauche déplace ses items par “bloc”. Lorsqu’on utilise une ListBox dans un contexte classique avec une seule ligne de texte pas trop grosse notre œil supporte la “saccade”. Mais dès qu’on template un peu et que les items sont assez gros comme ici l’effet visuel n’est vraiment pas terrible.
To be optimized or not to be ?
A cela une bonne raison : la ListBox est optimisée et utilise par défaut un conteneur spécial, un VirtualizingStackPanel. Ce type de StackPanel très particulier virtualise l’affichage des items, il ne prend en compte que ceux qui sont affichés et se règle uniquement sur ceux-là. Il ne peut pas connaitre à l’avance la taille des prochains items à venir (qu’ils viennent du haut ou du bas) : puisqu’ils ne sont pas affichés, il ne les connait pas. Grâce à cette optimisation la ListBox peut présenter des centaines, des milliers d’items sans jamais consommer plus de mémoire que ne le réclame le nombre d’items visibles.
Hélas, toute optimisation a un coût ! Ici il est visuel.
La souplesse de Xaml, l’intelligence de Blend et la ruse du développeur
Mais Xaml et donc Silverlight (ou WPF) sont tellement souples qu’il suffit simplement de modifier la nature du conteneur de la ListBox pour améliorer le choses.
La ListBox “hard”, celle de gauche dans notre exemple plus haut, a été conçue “tel quel”, rien n’a été modifié en dehors de l’ItemTemplate qui met en forme les trois propriétés de chaque enregistrement (une base de données, une source XML… ici j’ai utilisé la génération de données aléatoires intégrée à Blend plus quelques modifications des nombres ainsi que l’ajout d’un convertisseur pour obtenir un format monétaire).
Pour créer la ListBox “Smooth”, celle de droite donc, j’ai d’abord effectué un simple copier / coller. J’ai ainsi récupéré tout le visuel, l’ItemTemplate, le binding à la source de données, etc.
C’est maintenant que les choses deviennent super difficiles, soyez attentifs ça va aller très vite : Clic droit sur la ListBox, puis “modifier des modèles associés” / “Modifier disposition des éléments (ItemsPanel)” / “Créer un élément vide”. Ce qui ouvre le dialogue suivant :
Automatiquement l’affichage de Blend bascule en mode de modification de template, et regardez bien la capture ci-dessous :
ItemsPanel est déjà constitué d’un StackPanel, nous n’avons rien à faire puisque c’est justement ce que nous voulions : rempalcer le StackPanel virtualisé par un StackPanel de base. Fini. Ca va très vite, je vous avais prévenu (vous pouvez relire plus lentement pour voir tous les détails de l’action) !
Pourquoi ce changement automatique ? Blend lit-il dans mes pensées ?
Blend est très fort, mais pas à ce point là… La raison est autre : le StackPanel virtualisé n’est pas un composant disponible. Comme nous entrons en modification du template et que Blend ne peut pas nous afficher un composant auquel nous n’avons normalement pas accès, il le remplace par le plus proche, ici un StackPanel “normal”. C’est tout de même assez malin de sa part.
Du coup, rien de plus à faire, on sort du mode templating et F5 pour lancer l’application et au lieu d’une ListBox hard, nous avons maintenant une superbe ListBox ultra smooth…
La prochaine étape serait, par exemple pour application tactile Windows Phone 7, d’ajouter de l’inertie pour que les mouvements ressemblent plus à une “glissade”. Le premier pas est fait puisque nous disposons d’un StackPanel contenant en réalité tous les items à afficher. Mais nous verrons cela une autre fois.
Un monde presque parfait
En effet, en supprimant l’optimisation de la ListBox (son StackPanel virtualisé) nous avons beaucoup gagné côté visuel, mais nous avons perdu tout autant en termes de gestion mémoire. Désormais, si nous affichons 200 items dans la ListBox il faut savoir qu’un StackPanel classique sera créé ainsi que les 200 items à l’intérieur. L’affichage n’est plus qu’une sorte de clipping. Si le DataTemplate ou l’ItemTemplate est un peu gros (ou utilise des effets comme le DropShadow que j’ai placé sur l’image, image elle-même consommatrice de mémoire) on risque fort d’avoir de désagréables surprises !
L’astuce qui rend la ListBox “smooth” est donc à réserver à des cas parfaitement identifiés où l’on sait par avance et de façon sûre que le nombre d’items à afficher sera toujours assez limité.
Mais rappelez-vous qu’une liste ou une grille proposant plus d’une centaine d’items est souvent la preuve d’une analyse bancale ou d’une réalisation paresseuse, car aucun utilisateur au monde ne lit plus de deux pages. Ou bien il le fait parce qu’il n’a pas le choix mais il maudit le développeur sur 1000 générations !
Comme je ne vous souhaite pas un tel funeste destin, surtout pour votre innocente descendance (encore vous, vous l’avez bien cherché !), pensez à mettre la pédale douce sur les items que vous chargez dans les listes et les grilles ! C’est une erreur que je vois tellement souvent que ça devient une fixette. Je vous le redirait donc certainement dans un autre billet, histoire que cela rentre bien dans toutes les têtes, même les plus … hard !
Bon, on rit, on batifole, mais il n’y a pas de bonne compagnie qui ne se quitte, alors sur ce,
Stay Tuned !