[new:2/08/2010]Les command links sont ces petites boîtes qu’on voit dans les pages de Vista ou 7 qui comportent généralement une icône et deux lignes de texte et qui permettent de naviguer entre les pages de la doc, des options du système, etc. En voici un dérivé sous Silverlight.
Command Link à quoi cela ressemble ?
Ci-dessus un extrait de la doc MSDN montrant ce qu’est un Command Link. On reconnait ces boîtes ayant un filet bleu clair, une icône en haut à gauche, une ligne de titre et, en corps plus fin, juste en dessous, des explications. Lorsqu’on clique sur le titre on navigue vers la page dont il est fait état. Cela peut être une page Web externe ou bien une page de l’application elle-même.
Nous allons refaire la même chose pour Silverlight.
Créer le UserControl
Le plus simple est de créer une nouvelle application Silverlight et d’y ajouter un nouveau UserControl :
Créer le look
Le design d’un tel élément n’est pas très compliqué et nécessite juste de positionner une grille :
On ajoute au projet, dans un répertoire qu’on nommera Images de préférence, l’icône qui servira d’accroche. Vous pouvez mettre ce que vous voulez. Dans une version plus sophistiquée du UserControl il devrait être possible de placer l’icône de son choix. Mais un UserControl ne permet pas vraiment ce genre de chose. Il faudrait concevoir un Control (voir mon post Silverlight : Control vs UserControl) ce que nous ferons dans un prochain billet. Pour l’instant je vais choisir une petite flèche verte :
L’icône sera positionnée dans le coin supérieur gauche de la grille que nous avons créée. Cette dernière va maintenant être entourée par un border :
Deux TextBlock seront placés dans la grille. Un premier avec un corps assez gros, celui du dessous en plus petit (pour la taille c’est vous qui voyez, il faut que cela soit lisible sans être ni trop gros ni trop petit…).
Le résultat donne pour le moment :
C’est sobre et efficace.
Pour donner un peu de vie, nous allons créer une animation “MoveArrow” qui va déplacer la flèche vers la droite et la ramener à sa position (avec un easing pour que le mouvement soit plus agréable) :
L’animation est placée en mode auto-reverse comme cela nous n’avons qu’une moitié d’animation à créer et nous sommes sûr qu’à la fin de celle-ci la flèche aura retrouvé sa position de départ.
On notera que les couleurs de fond et d’avant plan sous reliées, par Template Binding, aux propriétés équivalentes du UserControl. De cette façon l’utilisateur du UC pourra modifier les couleurs sans entrer dans le code du UserControl. Car bien entendu, un UC ne se template pas (un Control oui, Cf le billet cité plus haut). Il faut donc prévoir dès le départ les façon externes de modifier les éléments principaux du look & feel.
Utiliser les behaviors
Grâce aux différents behaviors disponibles il est possible de “dynamiser” notre UserControl sans perdre de temps en code ou en animations supplémentaires.
Ici nous voyons un premier behavior : “ControlStoryBoardAction” qui est placé sous le UserControl. Dans la version finale j’ai préféré l’accrocher au Border. Ce behavior sera programmé pour se déclencher sur le MouseEnter (du Border donc) et déclenchera l’animation “MoveArrow”. A chaque fois que la souris entrera dans notre UC, la petite flèche s’agitera quelques instants pour montrer le titre de notre CommandLink.
On voit ensuite quatre ChangePropertyAction. Il s’agit d’une action (comme le précédent behavior) c’est à dire un Trigger (donc une condition de déclenchement). Et comme c’est un ChangePropertyAction, l’action réalisée quand le trigger sera déclenché est une modification de propriété.
Nous utilisons 4 instances car nous avons 2 changements à opérer, chacun avec un déclenchement d’entrée et de sortie (1 behavior pour chaque).
Le premier groupe concerne le titre. Je voulais mettre en évidence qu’il s’agit d’un lien et pas seulement d’un texte. Pour cela il suffit d’ajouter un souligné sous le titre, la plupart des gens sont habitués au Hyperliens qui se présentent comme cela. Il y a donc un behavior déclenché sur le MouseEnter qui ajoute un souligné au texte, et un autre sur le MouseLeave qui supprime le souligné.
Le second groupe concerne la couleur du titre qui va devenir plus claire à l’entrée de la souris et reprendre sa couleur en sortie. L’effet est bon mais il annule un peu la précaution d’avoir établi un Template binding sur le foreground du UC. Dans une version plus élaborée il faudrait éviter cette collision sur la propriété couleur du couleur en jouant non pas directement sur la couleur (choisie par l’utilisateur du UC normalement) mais sur sa transparence ou un autre effet qui ne “bricole” pas la même propriété. A vous de créer la V 2.0 :-)
Le code
Nous avons pu concevoir le look & feel totalement sous Blend, mais notre UC doit faire des choses, et là il faut du code…
Avant tout il lui faut des propriétés. Des propriétés de dépendances seront utilisées pour le titre, la cible de navigation, la description, etc. Les DP sont utilisables dans des bindings ce qui rendra notre UC plus versatile que l’utilisation de simples propriétés CLR.
Certes les DP sont plsu longues à écrire, mais il suffit d’avoir une macro adaptée sous VS et le tour est joué !
Ces propriétés seront complétées d’une description et d’une catégorie, sous Blend (ou VS) cela est plus pratique pour l’utilisateur :
On voit ci-dessus la catégorie “Command Link properties” ainsi que les diverses propriétés du contrôle.
Une propriété de dépendance s’écrit de la façon suivante :
ici on voit que le code de la propriété Title modifie la propriété Text de txtMain qui est un TextBlock, celui utilisé pour le titre.
Le fonctionnel
Notre Command Link est assez malin. Il expose une propriété basée sur l’énumération NavigationType qui peut prendre les trois valeurs suivantes : PageNavigation, BrowserNavigation et EventDriven.
le mode PageNavigation
Si le CommandLink est utilisé dans une application Silverlight utilisant la navigation SL, c’est à dire basée sur les classes Frame et Page, il pourra être utilisé pour changer de page dans l’application. La propriété NavigateTo indiquera l’URI de la page à atteindre. Dans ce mode notre UC cherche la page parente et utilise ses méthodes de navigation.
le mode BrowserNavigation
Ici, le CommandLink sera utilisé pour appeler une page Web. NavigateTo sera donc une adresse Internet, les propriétés Target et Options permettent de fixer la cible ‘_blank’ pour une nouvelle page par exemple. Les options permettent d’afficher ou non la barre de status, les menus de la page appelées, etc. Il s’agit là de pure HTML.
le mode Event Driven
Il se peut que l’application souhaite utiliser le CommandLink dans un autre contexte ou d’une autre façon. Dans le mode EventDriven, un clic sur le titre déclenchera l’événement OnNavigate qui passera en argument un instance de NavigationEventArgs, une classe créée pour l’occasion qui contiendra toutes les propriétés utiles du CommandLinks ainsi que la propriété Tag du composant (un contexte quelconque qui sera utilisé par l’application par exemple).
La méthode de navigation
Elle se présente comme suit :
1: private void navigate()
2: {
3: switch (NavigationMode)
4: {
5: case NavigationType.PageNavigation:
6: {
7: DependencyObject p = this;
8: do
9: {
10: p = VisualTreeHelper.GetParent(p);
11: } while ((p != null && (!(p is Page))));
12: if (p == null || (!(p is Page))) return;
13: var pp = (Page)p;
14: pp.NavigationService.Navigate(new Uri(NavigateTo, NavigationUriKind));
15: }
16: break;
17: case NavigationType.BrowserNavigation:
18: {
19: if (NavigateTo == null) return;
20: HtmlPage.Window.Navigate(new Uri(NavigateTo, NavigationUriKind), NavigationTarget, NavigationOptions);
21: }
22: break;
23: case NavigationType.EventDriven:
24: {
25: var n = OnNavigate;
26: if (n == null) return;
27: n(this, new NavigationEventArgs { Destination = NavigateTo, Options = NavigationOptions, Tag = Tag, Target = NavigationTarget, UriKind = NavigationUriKind });
28: }
29: break;
30: default:
31: throw new ArgumentOutOfRangeException();
32: }
33: }
Selon le mode de navigation choisi le UserControl exécutera une séquence de navigation différente.
Conclusion
Créer des UserControl n’est pas une opération complexe, certains détails doivent être soignés et j’ai souligné dans ce billet les endroits où il faudrait passer un peu plus de temps pour rendre l’ensemble plus propre.
Nous avons vu aussi quelques limitations de ce mode de création de “composant” : ils ne sont pas “templatables”, et ne sont pas facilement modifiables par l’utilisateur (par exemple ici changer l’icône n’est possible qu’en modifiant le UC lui-même).
C’est pour cela qu’il est bien plus intéressant de développer des Contrôles, ce que nous verront dans un prochain billet !
le code du projet (VS2010 / Blend 4 / SL 4) :
Stay Tuned !