Tutorial Silverlight 4 WCF RIA Services avec 0 ligne de code – partie 2
Article mis à jour : mai 2010 pour la sortie de Silverlight 4 RTW et WCF RIA Services RTW
Je vous ai montré dans ce 1er billet comment rapidement mettre en place une application RIA en moins de 5 minutes comme démontré aux Techdays 2010. Voyons voir maintenant comment mettre en place de la pagination, un contrôle jouant une animation pour faire patienter l’utilisateur pendant les opérations réseaux et la mise en place d’une vue maître/détail. Le tout… toujours sans la moindre ligne de code ! Tout cela est possible grâce aux nouveautés de l’éditeur Visual Studio 2010 couplé à Silverlight 4 et WCF RIA Services.
Reprenez le projet que vous avez réalisé à l’étape précédente. Sinon, vous pouvez le récupérer directement ici :
1 – Lancez Visual Studio 2010 et ouvrez la solution DemoKeynoteTechdays.sln construite à l’étape précédente. Ouvrez le concepteur sur le fichier Home.xaml
2 – On va voir ici une autre nouveauté intéressante du designer de VS2010 pour Silverlight pour mettre en forme les grilles par exemple. Cliquez sur l’icône “Document Outline”
Cela vous affiche alors l’ensemble des contrôles sous la forme d’une arborescence. Vous pouvez même avoir un aperçu de certaines zones au survol de la souris sur l’élément :
Cliquez sur l’élément de type Grid (layoutRoot). Ensuite dans la zone bleue sur le côté gauche, positionnez-y la souris. Un curseur en forme de croix apparaît vous permettant de découper la grille comme vous le souhaitez. Découpez la grille en 3 comme sur cette copie d’écran :
Cela a pour effet de générer le XAML suivant :
<Grid.RowDefinitions>
<RowDefinition Height="242*" />
<RowDefinition Height="34*" />
<RowDefinition Height="238*" />
</Grid.RowDefinitions>
Ensuite, il faut placer nos éléments au sein de ces lignes. Il faut revoir la position de notre grille de données. Commencez par sélectionner la grille acteursDataGrid (à l’aide du “document outline” éventuellement), déplacez-là et redimensionnez-là de manière à lui donner une taille inférieure à la 1ère section de notre grille comme sur la copie d’écran suivante :
Une fois l’opération effectuée, faites bouton droit sur la grille de données acteursDataGrid –> “Reset Layout” –> “All”. Votre grille de données devrait désormais remplir toute la 1ère section.
Tant que nous sommes sur la grille, nous allons revoir légèrement les informations qu’elle affiche. Pour cela, cliquez sur “…” à côté de la propriété “Columns” de votre “DataGrid” comme dans le tutorial précédent. Changez la valeur de la propriété “Header” de “Url Photo” à “Photo” pour notre 1ère colonne puis retirer de la vue actuelle les colonnes “Pays” et “Date Naissance”. Nous retrouverons ces informations dans la vue détails un peu plus tard.
3 – Pour mettre en place la pagination, il y a plusieurs choses à faire. Tout d’abord, il nous faut le contrôle “DataPager” dont c’est la mission ! Si vous ne l’avez pas encore dans la “Toolbox”, il nous faut l’ajouter. Pour cela, faites bouton droit –> “Choose Items… ” dans la zone que vous souhaitez. Dans la liste des contrôles proposés, filtrez sur le mot clé “datapager” et cochez le contrôle trouvé :
Ensuite, drag’n’droppez le contrôle “DataPager” dans la zone du milieu de notre grille, positionnez le contrôle au milieu de la zone puis faite bouton droit –> “Reset Layout” –> “All” comme vu précédemment. Vous devriez avoir ce résultat :
Dans les propriétés du “DataPager” (dataPager1 par défaut), changez la valeur de la propriété “PageSize” de 10 à 3.
Il nous faut maintenant indiquer quelle source de données nous devons piloter avec ce contrôle de pagination. Pour cela, afficher à nouveau l’arborescence “Data Sources” comme vu précédemment et drag’n’droppez la source “Acteurs” directement sur le contrôle “DataPager” dans le designer :
Au final, le designer de Visual Studio 2010 nous a donc généré ce XAML pour nous :
<data:DataPager Grid.Row="1" Name="dataPager1"
PageSize="3"
Source="{Binding ElementName=acteursDomainDataSource, Path=Data}" />
XAML que nous devions avant taper à la main si vous aviez suivi mes précédents tutoriaux sur .NET RIA Services avec Silverlight 3.
Dernière étape pour que la pagination fonctionne, il nous faut trier la source de données d’Entity Framework. Sinon, vous aurez une exception de levée. Pour cela, cliquez sur l’élément “DomainDataSource” dans le “Document Outline”, triez les propriétés avec le mot clé “Sort” et cliquez sur “…” sur la propriété trouvée nommée “SortDescriptors” :
Une fenêtre d’assistant apparaît. Ajoutez un tri simple sur le prénom :
Faites ok. Vous pouvez déjà tester l’application à ce niveau :
Comme il n’y a que 6 acteurs dans ma base et que nous avons demandé une pagination tous les 3 éléments, il n’y a que 2 pages proposées.
4 – Vous ne vous en rendez pas forcément compte mais le paging mis en place automatiquement pour vous est déjà intelligent. En effet, il retourne les pages vers le client uniquement au fur et à mesure de la navigation. L’ensemble des enregistrements n’est pas retourné directement en mémoire côté Silverlight. Sinon, la pagination aurait que peu d’intérêt. Lorsque vous naviguez dans les pages, la couche RIA Services s’occupe de sérialiser sur le réseau les requêtes qui vont bien pour piloter notre couche d’accès aux données. Notre couche d’accès aux données Entity Framework s’occupe alors de générer les requêtes SQL qui vont bien au près de notre serveur de base de données. Les données sont alors remontées à travers les différents tiers jusqu’au client Silverlight. Tout cela vous a donc bien été masqué !
Oui mais voilà, que se passe-t-il si la dernière remontée (le réseau entre le serveur web et le client Silverlight) prend du temps ? Il va falloir faire patienter l’utilisateur avec une animation d’attente. Commençons pas “simuler” une charge réseau en ajoutant un temps de traitement côté serveur web.
Rendez-vous dans “FilmService.cs” et remplacer la méthode GetActeurs() par celle-ci :
public IQueryable<Acteurs> GetActeurs()
{
System.Threading.Thread.Sleep(1000);
return this.ObjectContext.Acteurs;
}
Nous avons simplement ajouté la 1ère ligne simulant un temps de traitement de 1000 ms. Si vous recompilez et relancez le code, vous verrez ainsi que l’application se “fige” pendant 1 seconde lorsque vous passez de la page 1 à la page 2.
Afin d’améliorer l’expérience utilisateur, nous allons pendant ce temps là afficher un contrôle particulier nommé BusyIndicator. Retournez sur “Home.xaml”. Ajoutez un nouvel élément dans la toolbox en filtrant sur le mot clé "busy” comme dans la copie d’écran de manière à pouvoir ajouter le contrôle :
Note : si vous ne voyez pas apparaître ce contrôle c’est que vous n’avez peut-être pas encore installé le Toolkit pour Silverlight disponible ici : https://silverlight.codeplex.com . Par ailleurs, depuis la RTM des outils pour Visual Studio, le code source de ce contrôle est automatiquement intégré à un projet de type Business Template. Vous devriez donc le voir apparaître dans la zone "DemoKeynoteTechdays Controls" de la barre d'outils.
Ensuite drag’n’droppez le contrôle “BusyIndicator” sur la grille par exemple de manière à obtenir ce résultat :
Une fois l’opération effectuée, faites bouton droit sur le contrôle BusyIndicator –> “Reset Layout” –> “All”. Votre contrôle devrait désormais remplir toute la 1ère section.
Maintenant, il faut indiquer à quel moment ce contrôle doit apparaitre ou non. Pour cela, il faut mettre en place du binding entre éléments. Avant, il fallait taper le XAML à la main, maintenant on peut le faire facilement à travers le designer. Rendez-vous dans les propriétés de l’objet “busyIndicator1” et plus particulièrement sur la propriété “IsBusy”. Il faut la lier à la propriété IsLoading de notre domain context. Pour cela, cliquez sur l’icône violette à côté de la case à cocher puis choisissez “Apply Data Binding… ” :
Un assistant s’ouvre vous permettant de définir le binding. Dans la partie “Source”, liez “ElementName” à “acteurDomainDataSource” :
Ensuite, dans la partie “Path”, naviguez vers “DomainContext” –> “IsLoading” :
Cela a pour effet de générer le XAML suivant pour vous :
<controlsToolkit:BusyIndicator Height="68"
HorizontalAlignment="Left" Margin="198,99,0,0" Name="busyIndicator1"
VerticalAlignment="Top" Width="224"
IsBusy="{Binding ElementName=acteursDomainDataSource,
Path=DomainContext.IsLoading}" />
Alors ça veut dire quoi docteur ? La propriété “IsBusy” est un booléen indiquant au contrôle BusyIndicator à quel moment il doit s’afficher ou non. On a donc lié cette propriété au booléen “IsLoading” de notre domain context. Ainsi, dès qu’une opération de lecture depuis le réseau sera effectuée, le booléen “IsLoading” passera à vrai ce qui aura pour conséquence immédiate d’afficher notre contrôle d’attente. Lorsque la lecture sera terminée, le booléen “IsLoading” repassera à faux et notre contrôle disparaitra. Nous avons donc lié logiquement 2 contrôles entre eux toujours sans ligne de code.
Si vous lancez maintenant à nouveau notre application, vous verrez le contrôle d’animation pendant 1s au 1er démarrage de l’application puis lorsque vous allez passer de la 1ère page à la 2ème :
Par contre, une fois les pages en mémoire, vous observerez que vous pouvez naviguez d’une page à l’autre sans solliciter à nouveau la partie serveur.
5 – Dernière étape dans ce tutorial sans ligne de code, l’ajout d’une vue détail. Vous allez voir, c’est encore l’enfance de l’art. Retournez dans “Home.xaml” en mode designer et réafficher les sources de données (Data Sources). Cliquez sur la combobox “Acteurs” puis cliquez sur “Details” :
Ensuite, drag’n’droppez la source “Acteurs” (en mode détails donc) sur la 3ème et dernière partie de notre grille principale et positionnez correctement vers la gauche les contrôles obtenus. Vous obtiendrez logiquement ce genre de résultat :
Avant de tester le résultat, sélectionnez l’objet image de la vue détail (objet urlPhotoImage) et modifiez la valeur de la propriété “Width” de 200 à Auto. Recompilez et relancez l’ensemble. Vous verrez maintenant que la vue détail est automatiquement mise à jour au fur et à mesure de votre navigation sur la vue maître. Les règles de validation côté client fonctionnent également sur cette vue détail :
Allez pour le fun et pour terminer sur ce tutorial 0 ligne de code, nous allons ajouter un petit effet de Pixel Shaders sur l’image. Si vous souhaitez en savoir davantage sur les Pixel Shaders, j’avais fait un petit tutorial sympa à ce sujet. Revenons à notre projet et rendez-vous d’abord dans le XAML. Ajoutez ce morceau sous le contrôle Image “urlPhotoImage” :
<Image.Effect>
<DropShadowEffect />
</Image.Effect>
Si ensuite vous double-cliquez sur “DropShadowEffect” dans le XAML, vous verrez apparaître une fenêtre de propriété comme celle ci-dessous. Vous pouvez alors définir la couleur de l’ombre portée, la profondeur, etc.
Prenons par exemple une couleur légèrement rouge foncée et une profondeur de 10 et vous obtiendrez ce superbe résultat dans la vue détail :
Voilà. Dans le prochain tutorial, nous continuerons avec cette application pour voir comment enregistrer des modifications vers le serveur et comment mettre en place de la sécurité en fonction du niveau de login et/ou du rôle. Par contre, nous serons obligés (enfin !) de taper quelques lignes de code. :)
David
Comments
Anonymous
February 24, 2010
The comment has been removedAnonymous
February 25, 2010
The comment has been removedAnonymous
February 25, 2010
The comment has been removedAnonymous
March 09, 2010
Salut David, Super bien tes post ! Je débute tout juste dans Silverlight et C#. J'ai suivi ton exemple en utilisant une autre base (base SQL Server), que j'ai réalisé (1 seule table !!). Lorsque je fais les différentes manip, je lance l'appli et quand j'essaie d'aler sur l'onglet de mes données, ça plante. J'ai l'entête de mes colonnes et après je sors en erreur (TargetInvocationException was unhandled by user code). Il me renvoie à la procédure IQueryable. Faut il changer du code pour attaquer sur SQL Server ? Merci d'avance Bye, VincentAnonymous
March 10, 2010
Bonjour Vincent, Merci :) Dans mes exemples, j'attaque déjà aussi SQL Server (Express) 2008. Il faudrait nous en dire plus sur ce que tu as fait. Je te propose de soumettre ton problème sur les forums de développez.com sur lesquels je vais souvent et où il sera plus simple de discuter avec toi de tout cela : http://www.developpez.net/forums/f915/dotnet/general-dotnet/silverlight/ Bye, DavidAnonymous
March 14, 2010
Bonjour, En effet très bons articles ! Silverlight gagne du terrain dans le combat des RIA. J'ai quelques soucis sur ces fichiers, tout d'abord j'arrive à compiler mais les fichiers compilés me donnent juste le loading en boucle ... Et quelle est la différence majeure entre une Business app et une Navigation app dans la création de projets ? Et une dernière ... Peut-on envisager des cookies qui contiendraient les informations de login ? (pour rester connecté par exemple même si on quitte l'application). Merci d'avance pour vos réponses ! Je suis de plus en plus curieux de SL.Anonymous
June 03, 2010
The comment has been removedAnonymous
January 02, 2011
Merci pour ces tutos qui sont très bien pour un débutant comme moi. J'ai une problématique qui est la suivante : J'ai une page contenant les liens suivants :
- Liste des films
- Liste des Acteurs
- ... Je souhaiterais que quand on clique sur "Liste des films" qu'on accède à une page affichant la liste des films, et quand on clique sur "Liste des Acteurs" qu'on accède à la même page mais qui afficherait la liste des acteurs. De manière globale, j'ai une base avec plusieurs tables, et j'aimerais utiliser les mêmes contrôles pour afficher leur contenu. J'espère avoir été suffisamment clair. Suis-je obligé de créer un contrôle pour chaque table (je ne pense pas :) ? Quel serait la solution la plus adaptée pour cela ?
- Anonymous
June 30, 2011
Bonjour, J'ai l'erreur suivante si ma source de données est une vue SQL Server, au lieu d'une table : "Load operation failed for query 'GetV2PresenceSce'. La référence d'objet n'est pas définie à une instance d'un objet." où v2PresenceSce est le nom de ma vue. Merci pour votre réponse. Anne-Marie