Silverlight Analytics Framework

 

Faire une application Silverlight c’est bien.

L’exposer sur le web, c’est mieux.

Avoir des utilisateurs c’est top.

…Mais combien d’utilisateur j’ai ? Et que font-ils sur mon application ?

Genre la feature de la mort qui tue que j’ai mis 2 semaines à dev est-elle utilisée ?

Appart aller faire du porte à porte auprès de vos utilisateurs, ce genre d’informations n’est pas facile à obtenir (quoique le porte à porte ne l’est pas non plus)

Bien sûr il est possible d’envisager de se recoder une petite librairie qui va loguer l’ensemble des actions de vos visiteurs et ensuite passer encore des jours entiers à vous faire un panel pour voir l’ensemble de ces informations de façon pratique.

Ou bien…il vous suffit d’utiliser Silverlight Analytics Framework qui fait le café pour vous.

Ce Framework est juste bien fait :) .

Son nom devrait je trouve évoluer car même si au départ penser pour du Silverlight, il est maintenant compatible avec l’ensemble des technologies WP/E (WPF, Silverlight, WP7).

Son but est d’offrir de manière très simple une manière de logguer les actions des utilisateurs sur nos applications et au lieu de refaire le monde, utilisez les panels qui existent déjà pour nous afficher l’ensemble des informations collectées.

Prenons un exemple concret :

Vous avez une page de votre application qui porte le doux nom de MyKillerFeature qui contient un truc qui déchire tout sur le plan technique, il serait bon de savoir si vos utilisateurs s’en servent.

Le Framework va vous permettre de savoir d’un part si vos utilisateurs cliquent sur le lien de votre page mais également le temps qu’ils passent dedans et/ou les actions qu’ils font dedans.

Et c’est là que vous allez vous rendre compte que même pas 10% vont voir et qu’en moyenne ils y restent moins de 5 secondes tellement la KillerFeature est sans intérêt pour eux, simple et pauvre user  lambda:).

Mais comment cela marche me direz-vous ?

Simplement je répondrais !

Tout ce fait dans Blend (rien ne vous empêche de loguer des choses dans le code-behind !) d’une façon vraiment simple et a la porté du premier designer venu !

Comme nous l’avons vue, la force du Framework est de se reposer sur l’existant en termes d’outil d’analyse, donc avec un peu de chance, votre favori est déjà géré par le Framework.

Une fois le Framework installé, ouvrez votre page xaml puis glisser le behavior d’analyse qui vous convient sur le layout principal, pour ma part je vais prendre googleAnalytics et le configurer avec le code UA obtenu sur mon compte Google.com/analytics.

La marche à suivre étant la même avec les autres outils d’analyse, il vous suffit de rentrer votre code de tracking(ou identifiants divers).

clip_image001

clip_image002

Voilà, nous avons maintenant fait le plus dur, oui oui !

Lors de l’ouverture du menu behavior vous avez pu voir qu’il en existe beaucoup :

· Plusieurs du type *Analytics, comme nous l’avons vu ce sont nos outils d’analyse et rien ne vous empêche d’en mettre plusieurs à la fois.

· Des Track*, ce sont ces behaviors qui vous permettent…et bien de tracker les actions utilisateurs.

Prenez un exemple simple, glissez un TrackAction vers vos boutons de menu, vérifiez que leur events sont bien réglés sur « Click » et…et bien c’est tout.

Au runtime, les behaviors vont « communiquer » ensemble pour transmettre les informations vers votre interface d’analyse, dans mon cas Google analytics.

A noter que lors de la collection des events, chaque Track* remonte le nom du contrôle auquel le behavior est attaché, il est donc judicieux de donner des noms « propres » a ses contrôles ;) .

Je ne vais pas répéter longuement la doc en vous listant l’ensemble des behaviors disponible mais en bref :

-actions de type event classique

-action de navigation

-action de formulaire (quelles sont le top5 des recherches faites ?)

-action de type Media (combien de temps l’user moyen regarde ma vidéo avant de la stopper ?, est-il passé en fullscreen ?)

-bien d’autre (et rien ne vous empêche bien sûr d’ajouter les vôtres au besoin.

Voilà un Framework qu’il est bon et pratique :) .

Qui plus est, bien fait, on y retrouve des fonctionnalités agréable telles que :

· Gestion des applications Out of Browser

· Gestion du mode offline (envois des stats une fois online)

· Gestion totalement par behavior, ne réclame aucune ligne de code

· Gestion du A/B Testing (offrir une interface particulière (VisualState powered) à 10% de ses users et voir leurs réactions)

Et une liste d’outils d’analyse qui s’agrandit encore régulièrement :

clip_image004

La liste ne vous convient pas ? Votre outil n’est pas dessus ?

Un behavior vous permet d’indiquer un endpoint « home-made » pour les datas donc ajouter votre panel d’analyse perso ne devrait pas être bien long.

Et ensuite rien ne vous empêche de faire un behavior spécial pour votre panel et l’offrir (ou non) a d’autre utilisateur.

Le résultat ? Dans le cas de Google analytics, les statistiques sont disponible chaque nuit sur les coups de minuit, voici celle que j’ai récupéré pour mon petit sample :

clip_image005

clip_image007

On retrouve les catégories que j’ai indiquées dans mes behavior et la répartition du type d’action qui ont été logués.

Si on explore un peu les sous menu, on peut avoir de nombreux détails.

clip_image009

A vous d’avoir une nomination correcte pour vous y retrouver.

Voilà, je pense que nous avons fait un tour rapide de qu’est-ce que Silverlight Analytics Framework et comment l’utiliser pour obtenir un maximum d’information sur ses utilisateurs.

Mettre en place une solution de surveillance sur ses sites est devenu une habitude/obligation depuis quelques années maintenant mais ce n’est pas encore un réflexe au niveau applicatif.

Pourtant nous avons beaucoup à apprendre des habitudes de nos utilisateurs :) .

Je vous invite tout de même a prévenir sur vos applications que des informations quand a son utilisation sont envoyées ;) , offrir un moyen d’activer ou non cette option est également des plus conseillé pour éviter tout ennuis.

L’activation ou non peut ce faire simplement avec quelques lignes de code.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: .Net, Blend, Silverlight, WPF Tags: , , ,

Visual Studio LightSwitch

vs_lightswitch_beta_logo

Ou comment créer une application pour manipuler ses datas en quelques clics.

Car oui c’est le but, en soit rien de très nouveau mais pour une fois le produit semble vraiment prometteur et complet.

Loin d’etre une solution parfaite pour tous les cas mais cela peut depanner ;)

J’ai un profil dev donc par principe j’aurais tendance à penser que ce type de logiciel va finir par nous mettre sur la paille mais au final, pas si sûr.

En quelques mots, LightSwitch est un designer d’application, qui va en 2/3 clics permettre d’obtenir un client lourd et/ou léger pour manipuler ses bases de données, ou…toutes sorte de données.

Aucunes connaissances techniques n’est requis pour l’utiliser, il fonctionne comme un stand-alone a Visual Studio 2010 mais s’y couple parfaitement si vous avez déjà VS sur votre poste.

Et pour l’avoir essayé, je ne peux qu’affirmer que cela fonctionne vraiment bien.

Pour un projet sur lequel nous bossons actuellement au sein des laboratoires de jeux vidéo et Microsoft d’Epitech, nous avions besoin d’un panel administrateur rapidement.

LS a répondu à notre besoin en quelques minutes.

Et vu nos délais sur ce projet, les heures…journées gagnées seront plus qu’utiles sur le projet!

Et hop, une interface d’admin de nos db sur Azure de faite!

Lors de la création d’un projet LS, il vous est possible de choisir C# ou VB, pourquoi donc si tout ce fait au clic ?

Car à l’inverse de beaucoup de générateur d’interface admin (ou autre), LS n’est qu’un type de projet .Net parmi tant d’autre.

Apres après poser de solides bases avec l’éditeur, rien ne vous empêche d’ouvrir le projet comme un projet C# (ou VB) et de le personnaliser un maximum par l’ajout de fonctionnalités spécifiques à votre projet par exemple.

Voici quelques screen pour vous montrer un processus de création, a noter que j’ai pressé F5 après le cinquieme screen seulement.

1. création du projet

1

2. création d’une db ou récupération d’une existante

2

3. on choisi les tables que l’on veut gérer

3

4. il nous reste plus qu’a ajouter des “screen”, chacun etant relié a une source de Data5

5. on arrange un peu notre Screen si le besoin ce fait sentir

6

6. on lance notre programme et voila!

7

Après cette première étape, il vous est possible de choisir si vous souhaiter un mode d’authentification, une application Desktop ou Web, …, …

La rapidité de création est vraiment agréable et surtout, pour une fois on obtient quelque chose de cohérent et modifiable.

Un non informaticien est capable de faire son interface lui-même et ensuite si il désire rendre le panel un peu plus “maison” pour des besoins précis, c’est là que nous les dev on entre en jeu.

Il nous suffit de récupérer le projet, l’ouvrir comme un projet .Net classique et mettre les mains dans le code comme on adore le faireclip_image001.

Ah dernier point, pour ceux n’ayant pas de compte MSDN, une beta public est prévu a la fin du mois clip_image001[1].

http://www.microsoft.com/visualstudio/en-us/lightswitch

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: .Net, Microsoft Tags: ,

XNA dans une Image WPF

08/08/2010 Stumpy 2 commentaires

Le problème de mélanger ces deux technologies que sont WPF et XNA existe depuis leurs débuts, chacune étant fort performante dans son domaines mais dans certains cas, nous aimerions bien pouvoir mixer les deux.
Au hasard, un éditeur d’environnement pour jeux vidéo ;) .

Il existe plusieurs solution plus ou moins viables, on peut citer par exemple le classique WindowsFormHost qui marche mais implique certaines limitations comme l’impossibilité de poser des contrôles WPF par-dessus le rendu XNA.
Valentin Billotte propose quant à lui une méthode différente et qui pour l’avoir vu tournée marche plutôt bien mais certains ont quelques réticences pour l’utiliser en raison de son principe de superposition des rendu

Par le biais de mon travail de recherche sur le produit Artlantis.com, une idée a germée dans mon esprit mais est restée bien longtemps tranquille par manque de temps.
Il y a peu, je suis tombé sur un forum ou quelqu’un évoquait cette même idée mais n’avait pas vraiment fait de proof-of-concept donc je me suis dis que c’était le bon moment !

Une fois expliqué en détail le process, un de mes collègues sur le projet de fin d’étude que je lead (PrismEngine), Alexandre Bossard nous a mis rapidement en place ce proto pour démontrer que oui cette solution est viable !
La solution a été un peu retouché car est maintenant notre méthode de rendu au sein de notre éditeur mais voici la marche à suivre si vous souhaitez essayer cette méthode qui pour le moment ne nous a pas déçu.

A noter que cette solution est viable pour un éditeur mais je ne promets rien pour un jeu ;) , d’une part utilisation de WPF donc aucune porta sur Xbox360/Zune/WP7 mais surtout malgré un FPS tout à fait correct, la transformation reste couteuse.

Son avantage est de garder toute la puissance de WPF, avec une modification minimum de votre class Game coté XNA.
La seule chose « contraignante » est la partie input qu’il faut légèrement surcouché car on ne travail plus directement sur le rendu XNA mais une simple Image WPF.
Oui, oui, une simple Image WPF donc aucuns soucis pour y ajouter divers contrôle, effet graphique et autre choses marrantes :) .

Voici la marche à suivre pour faire le premier proto, une bonne réorganisation est utiles pour rendre les choses plus élégantes mais allons au plus simple pour comprendre l’idée!
Dans l’ordre nous aurons besoin de :
1. Un projet XNA pour PC que l’on compilera sous forme de library et non exécutable (pour pouvoir l’embarquer au sein de l’appli WPF
2. Une appli WPF dans laquelle on ajoute une référence vers Microsoft.Xna.Framework.Game

Préparons notre class Game maintenant :
On y ajoute quelques « helpers » qui vont nous servir a faire le gros du travail

RenderTarget2D target; // Nous allons dessiner notre scene dedans
public WriteableBitmap bitmap = new WriteableBitmap(800, 460, 96, 96, System.Windows.Media.PixelFormats.Bgra32, null); // l'image que nous donnerons a WPF pour l'éditeur
Color[] colors = new Color[800 * 460]; // le tableau pour remplir notre image
private System.Windows.Threading.DispatcherTimer timer; // un timer, nous allons nous passer du cycle XNA classique donc il faut simuler nos ticks

Au sein de votre Constructor, nous allons ajouter 3 choses:

// on fix une hauteur et largeur en rapport avec notre image, bien sur ensuite ce morceau se devra de gérer les changements de résolution au runtime
this.graphics.PreferredBackBufferHeight = 460;
this.graphics.PreferredBackBufferWidth = 800;
this.graphics.ApplyChanges();
//on appel différentes méthodes de la classe Game manuellement, nous ne passerons pas par le cycle XNA donc c'est a nous de le faire
this.Initialize();
this.LoadContent();
//on lance le timer qui va nous permettre de gérer nos Ticks
this.timer = new System.Windows.Threading.DispatcherTimer();
this.timer.Interval = new System.TimeSpan(5000);
this.timer.Tick += new EventHandler(this.EngineTick);
this.timer.Start();

dans le LoadContent, nous allons initialiser notre RenderTarget:

this.target = new RenderTarget2D(graphics.GraphicsDevice, 800, 460, false, SurfaceFormat.Bgra4444, DepthFormat.Depth24, 0, RenderTargetUsage.DiscardContents);

Et viens la seule partie qui implique vraiment quelques changements dans votre code, la méthode Draw.
Au lieu de le faire de manière classique, nous allons rendre l’image dans notre texture puis ensuite copier son contenu au sein de notre WriteableBitmap qui sera l’image que nous donnerons a l’interface WPF.

protected override void Draw(GameTime gameTime)
{
    graphics.GraphicsDevice.SetRenderTarget(target); // on indique que l'on veut rendre dans notre RenderTarget
    GraphicsDevice.Clear(Color.CornflowerBlue);

    // TODO: Add your drawing code here

    base.Draw(gameTime); // on rend notre scene
    graphics.GraphicsDevice.SetRenderTarget(null);
    target.GetData<Microsoft.Xna.Framework.Color>(colors) // on recupere les pixels de notre scene
    // Bridge wpf/xna
    // Nous allons ecrire dans notre WriteableBitmap et lui assigner les pixels de notre scene
    bitmap.Lock();
    unsafe
    {
        int bb = (int)bitmap.BackBuffer;
        foreach (Microsoft.Xna.Framework.Color color in colors)
        {
            *((int*)bb) = color.B | (color.G <<  8 ) | (color.R << 16) | (color.A << 24);
            bb += sizeof(IntPtr);
        }
    }
    bitmap.AddDirtyRect(new System.Windows.Int32Rect(0, 0, 800, 460));
    bitmap.Unlock();
}

On remarque que l’utilisation d’un peu de code unsafe est obligatoire, la doc msdn est d’accord avec nous sur ce point, pensez donc bien a activé le code unsafe dans les propriétés de votre projet.

Dans notre Windows WPF, il nous suffit maintenant d’instancier notre classe Game mais au lieu de faire appel à la méthode Run qui va d’elle-même créer une fenêtre de rendu et faire appel aux méthodes Init, load,…, chose que nous ne voulons pas, nous allons laisser faire notre Constructor légèrement modifié.

Voici le code-behind de ma fenetre de test :

public partial class MainWindow : Window
{
    XNAPart.Game1 game;

     public MainWindow()
    {
        InitializeComponent();
        this.Init();
    }

     private void Init()
    {
        this.game = new XNAPart.Game1();
        // le fichier XAML de notre Windows comporte un controle de type Image qui porte le nom "Preview", on lui assign l'image de notre jeu
        this.Preview.Source = this.game.bitmap;
    }
}

Pas trop compliqué pour un résultat vraiment sympa et agréable à utiliser :) .
Petite preview avec le rendu XNA dans l’image du haut, un petit bouton par-dessus et un coup de visualBrush à partir de notre Image, chose impossible par exemple avec la méthode du WindowFormHost.

XNAinsideWPF

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: C#, Prism Engine, WPF, XNA Tags: , , , ,

Clavier virtuel XNA sur WP7

J’ai continué un peu mes recherches pour au final trouver le moyen d’avoir le clavier virtuel sous XNA.
C’est suite à une demande d’une connaissance que j’ai eu besoin de chercher cela et au finale la solution était toute bête.
Bon ce n’est pas encore un HUD complet en Silverlight mais c’est déjà pas mal pour rentrer un pseudo de HighScore par exemple :D .
Avec une « fake » textbox, moyen de faire une formulaire complet.

TouchPanel.EnabledGestures = GestureType.Tap; // On enregistre la gesture "Tap" dans celle a surveillées
if (TouchPanel.IsGestureAvailable && TouchPanel.ReadGesture().GestureType == GestureType.Tap)
{
    // On a "tap" l'écran, on affiche donc le clavier pour demander un pseudo
    Microsoft.Xna.Framework.GamerServices.Guide.BeginShowKeyboardInput(PlayerIndex.One,
        "HighScore", "Please enter your pseudo:", // Titre et Sous Titre
        "Stumpy", // Texte par defaut
        (IAsyncResult ar) =>
            {
                string ret = Microsoft.Xna.Framework.GamerServices.Guide.EndShowKeyboardInput(ar);
                Debug.WriteLine(ret);
            }
        , null);

Dans la foulé, un code permettant d’afficher une MessageBox en XNA.

Microsoft.Xna.Framework.GamerServices.Guide.BeginShowMessageBox("Title",
                   "Texte",
                   new List<string> { "OK", "42" }, // list des boutons, maximum deux
                   1, // bouton qui a le focus
                   MessageBoxIcon.Error, // icone de la Messagebox
                   (IAsyncResult ar) =>
                   {
                        int? ret = Microsoft.Xna.Framework.GamerServices.Guide.EndShowMessageBox(ar); // ret prend la valeur de l'index du bouton cliqué
                   }
                , null);

A savoir que le code pour le clavier marche également sur une application Silverlight (une fois les deux références XNA ajoutées) pour si un jour le besoin arrive d’avoir une entrée utilisateur sans que ce dernier clique explicitement sur une TextBox, oui sait-on jamais :) .

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: Silverlight, WP7, XNA Tags: , ,

Snippets pour WP7

Petite session reflector pour regarder les entrailles des assembly Windows Phone 7.
Je n’ai pas trouvé ce qui m’intéressais en premier lieu…du moins pas encore mais voici déjà quelques petites morceaux de code qui pourront servir lors de vos devs.

Pour faire vibrer le téléphone :

Microsoft.Devices.VibrateController.Default.Start(TimeSpan.FromSeconds(5));

5 secondes étant le maximum possible.
Un appel de la methode Stop() pour arrêter avant la fin du temps défini.

Pour savoir si votre programme s’exécute sur l’émulateur ou un appareil :

var type = Microsoft.Devices.Environment.DeviceType;
// type peut prendre comme valeur
// Microsoft.Devices.DeviceType.Device
// Microsoft.Devices.DeviceType.Emulator

Pratique pour faire un peu d’abstraction, on peut penser par exemple aux services de géolocalisation qui fonctionneront sans nul doute mieux sur un appareil ;) .

Voici une ébauche de Wrapper à utiliser :

public class Wrapper
{
    public Wrapper()
    {
        if (!DesignerProperties.IsInDesignTool)
        {
            // on s'execute sur emulateur ou device
            this.RuntimeCode();
        }
        else
        {
            // on s'execute en mode design (Blend), on peut injecter ici des datas pour tester l'interface
            // Design code
        }
    }

    private void RuntimeCode()
    {
        if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device)
        {
            // sur un device, on peut utilise les services sans soucis
        }
        else
        {
            // sur emulateur, il faut faker le comportement des services
        }
    }
}

L’ensemble est séparé car tester le mode édition ne suffit pas toujours à éviter les erreurs dans Blend, le reste du code étant malgré tout précompilé.
En separant les deux test, on est certain de n’avoir aucun soucis ni erreur dans chacun des trois cas.

Microsoft.Devices.Radio.FMRadio.Instance.CurrentRegion = Microsoft.Devices.Radio.RadioRegion.Europe;
Microsoft.Devices.Radio.FMRadio.Instance.PowerMode = Microsoft.Devices.Radio.RadioPowerMode.On;
Microsoft.Devices.Radio.FMRadio.Instance.Frequency = 101.1;

Le code pour utiliser la radio, ne provoque aucune erreur a l’exécution mais pas moyen de savoir actuellement si cela sera « disponible » au sein des applications.
MSDN n’indique pas que son utilisation sera bridé mais la page est encore bien vide…

var licence = new Microsoft.Phone.Marketplace.LicenseInformation();
var trial = licence. IsTrial();

Permet bien entendu de savoir si l’application tourne en mode trial ou non mais on peut remarquer également une sous classe internal

internal static class NativeMethods
{
    // Fields
    internal const int S_FALSE = 1;
    internal const int S_OK = 0;
}

Cela peut confirmer que certaines applications auront bien le droit de faire un peu de natif selon le bon vouloir de Microsoft.
Oui l’init actuel n’est pas vraiment motivante ;) mais cela a la mérite d’être présent…
Voilà pour le premier jet, il me reste pas mal de chose à explorer mais j’ai peur de devoir plonger un peu plus dans le code pour la suite, les choses apparentes sont déjà bien connu en général.
Si des gens ont des pistes sur comment :

  • Utiliser le clavier virtuel sur demande (Silverlight et XNA)
  • Utiliser Silverlight au sein d’une application XNA (ou l’inverse mais en évitant le WritableBitmap ;) )
Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: Blend, C#, WP7 Tags: , ,

Client VDM sur Windows Mobile 7

18/07/2010 Stumpy 2 commentaires

TileVdmCe soir, je tournais un peu en rond donc j’ai voulu mettre en pratique les notifications qui ont fait le thème de mon dernier article.

Pour cela, j’ai repris une vieille source de mon lecteur de viedemerde.fr qui trainait dans mes tiroir depuis bien longtemps et j’ai fais une petite mise à jour.

Ajout d’un contrôle Pivot pour naviguer au sein des différentes catégories, possibilité de se loguer sur son compte pour être en mesure de voter mais surtout…les notifications de nouvelles VDM sur le téléphone par deux moyens:

  1. Une Toast notification qui indique la publication de nouvelles VDM
  2. Une Tile notification qui permet d’avoir toujours sous les yeux le nombre de VDM que l’on n’a pas encore lu

Ces deux notifications sont faite par le biais d’un serveur sur lequel le client WP7 s’abonne et indique qu’il désire être mis au courant lors de nouvelle VDM sur le site viedemerde.fr

Tout cela tiens en seulement quelques lignes et même si cela manque encore un peu d’une petite touche “artistique”, on peut déjà voir une application sympa et pratique (si si, lire les VDM c’est pratique car permet de se détendre :) ).

Voici une petite vidéo faite rapidement pour faire le tour de l’application.

 

Demo de cette premiere version de mon client VDM pour WP7

 

Il faut encore terminer la page de configuration pour par exemple pouvoir gérer la langue des VDM mais également ajouter l’inscription et une troisième page pour l’envoi de VDM.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: General Tags:

WP7 Push Notifications

logo-windows-phoneWindows Phone 7 approche doucement mais surement et ces derniers jours nous avons eu le droit de toucher à la version beta du SDK.

Depuis l’annonce, je suis de plus ou moins près ce nouveau OS mobile et j’en suis plutôt content dans l’ensemble, certaines limitations techniques me laisse un peu perplexe en ma qualité de dev malheureusement…

Les vidéos des devices sont sympas et…la réalité l’est tout autant ;) donc je voulais m’y intéresser d’un peu plus près après les classiques petites applications de rss reader et autre meteo reader, j’ai voulu regarder le système de notifications.

Ces notifications permettent de s’abonner à un channel de diffusion et ensuite d’être informé par le biais d’event un peu près n’importe quand (et donc même quand l’application “dort” en background).

Bon le concept…rien de bien nouveau et de magique mais comme d’habitude, le SDK est vraiment bien fait et assez souple pour permettre une intégration rapide et surtout facile au sein de nos applications mais egalement de n’importe quelles applications client/desktop/serveur.

Je ne vais pas m’étendre sur la création d’appli simple sur WP7, il commence a y en avoir un peu partout sur le net mais plus vous montrer comment en quelques lignes, on peut recevoir des notifications sur son application.

Nous allons découper cela en deux étapes, la première sera bien entendu de préparer son application à recevoir des notifications et réagir en conséquence.

La seconde sera la mise en place d’une plateforme d’envois, cela peut-être un peu près n’importe quoi…ah non enfaite n’importe quoi capable d’envoyer une requête HTTP (oui autant faire simple).

Comme évoqué, nous devons passer par un channel, il suffit d’imaginer cela comme un tuyau ou des messages peuvent se mettre en attente d’être consommé par l’application.

public HttpNotificationChannel myChannel;

A savoir que le channel pour une application peut changer entre chaque lancement mais pas obligatoirement donc il faut prendre en compte ce cas:

myChannel = HttpNotificationChannel.Find("MyChan"); //ou MyChan est un nom permettant de le retrouver par la suite a coup de ce .Find

Les deux cas:

1. Le channel existe déjà, il nous suffit de nous y abonner (if myChannel != null)

2. Le channel n’existe pas et/ou plus, on va donc l’ouvrir puis s’y abonner

Pour ouvrir notre channel, deux instructions:

myChannel = new HttpNotificationChannel("MyChan");
myChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myChannel_ChannelUriUpdated);
myChannel.Open();

Bon d’accord…trois instructions car l’event ChannelUriUpdated est là pour nous informer que l’adresse de notre channel, assez pratique pour la communiquer aux autres (les “senders”).

En version simple, voici la méthode en question:

void myChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
    Debug.WriteLine("Notification channel URI:" + e.ChannelUri.ToString());
}

La, bien sûr il faut imaginer implémenter l’envoi de cette uri vers un server ou un autre client pour qu’ils sachent par ou envoyer les notifications.

Je vous laisse mettre en place cette partie, en fonction de vos besoins.

Il existe trois types de notifications possibles, chacune ayant un rôle particulier et un “champs d’action”

1. Les Raw notifications, système le plus “ouvert” car permettant d’envoyer un peu près ce que l’on veut, c’est donc la façon pour communiquer avec son application tout ce qui concerne la logique de l’application.

2. Les Tile notifications, sont celle pour mettre à jour la tile de l’application si celle-ci est “pin to start” (comprendre par la, mise en avant sur la page d’accueil du téléphone), on peut faire varier l’image mais également un compteur (prenons exemple du nombre de mail non lu) et le titre de la tile

3. Les Toast notifications, elles permettent d’afficher un petit bandeau en haut de l’écran qui contient l’icône de l’application, un titre et un sous-titre. Utile pour par exemple informer qu’une chose est arrivée dans l’application et si on clique dessus, l’application s’ouvre.

Voici une illustrations pour les Tile et une pour les Toasts, les autres n’ayant pas de visuel ( sauf si choix du développeur)

Un exemple de tile:

wp7Tile3

Un exemple de Toast:

wp7Toast

Ensuite il suffit de brancher notre channel au shell du telephone, pour cela:

myChannel.BindToShellTile(); //pour s’abonner aux Tiles

Suffit pour cela.

Nous allons pour le reste ajouter le bind des toasts:

myChannel.BindToShellToast(); //pour s’abonner aux Toasts
/* pour recevoir les Raw */
myChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(myChannel_HttpNotificationReceived);
/* gestion des erreurs */
myChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myChannel_ErrorOccurred);

Et un event nous permettant de gérer les erreurs.

Celui du milieu étant pour gérer les Raw :) .

Je ne vais pas m’étendre sur les raw, il faut savoir que l’on envoie un buffer dans ce type de notification donc ensuite le protocole de communication dépend entièrement de l’application cible, il faut mettre en place une API que l’envoyeur comme le destinataire connait.

Une fois l’event levé, il vous suffit de lire le contenu de e.Notification.Body pour y entrainer vos informations.

Rien de plus n’est nécessaire, nous somme déjà en mesure de recevoir tout ce qui nous intéresse!

Passons donc à l’envois de notification, on part du principe que vous avez communiqué l’adresse du channel a un serveur qui par exemple va de temps en temps envoyer une notification vers les clients abonnés.

Dans notre exemple nous simulerons cela par une adresse superbement gérer au sein d’un copier/coller car c’est bien plus classe au sein d’un tuto :) .

Etudions déjà la structure des messages à envoyer dans le cas d’un Toast ou d’un Tile, à savoir que c’est encore sujet a modification donc dans le cas d’une mise à jour, si cela ne marche plus, pas de panique, il suffit d’aller voir sur la page MSDN la nouvelle version: http://msdn.microsoft.com/en-us/library/ff402545%28v=VS.92%29.aspx

Dans le cas d’un Tile, on va donc envoyer:

string tileMessage = String.Format("Content-Type: text/xml\r\nX-WindowsPhone-Target: token\r\n\r\n" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Tile>" +
"<wp:BackgroundImage>{0}</wp:BackgroundImage>" +
"<wp:Count>{1}</wp:Count>" +
"<wp:Title>{2}</wp:Title>" +
"</wp:Tile> " +
"</wp:Notification>", this.Image.Text, this.Count.Text, this.Message.Text);

On voit donc trois paramètres servant à:

1. Indiquez l’image à mettre en background de Tile, doit être contenu dans l’application ou à télécharger sur un serveur “autorisé” (lors du BindToShellTile, une surcharge permet de lister les serveurs “autorisés”, image qui doit prendre moins d’une minute à se télécharger!)

2. Un compteur, par exemple le nombre de mail non lu

3. Un titre, je vous laisse deviner

Et dans le cas d’un Toast:

string toastMessage = String.Format("Content-Type: text/xml\r\nX-WindowsPhone-Target: toast\r\n\r\n" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Toast>" +
"<wp:Text1>{0}</wp:Text1>" +
"<wp:Text2>{1}</wp:Text2>" +
"</wp:Toast>" +
"</wp:Notification>", this.Message.Text, this.SubMessage.Text);

Cette fois ci, deux paramètres:

1. Un titre

2. Un sous-titre

Et là on se demande ou l’envoyer? Et bien tout simplement vers notre adresse de channel donne par l’application et que l’on va donc récupérer sur notre serveur ou…dans le buffer magique du copier/coller :D .

Pour cela, je ne vais pas m’étendre sur l’explication de ce code, rien de bien mystérieux:

HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);
sendNotificationRequest.Method = "POST";
sendNotificationRequest.Headers = new WebHeaderCollection();
sendNotificationRequest.Headers.Add("X-NotificationClass", codeHeader);
byte[] notificationMessage = Encoding.Default.GetBytes(msg);
sendNotificationRequest.ContentLength = notificationMessage.Length;
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
    requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}
response = (HttpWebResponse)sendNotificationRequest.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];

Il nous suffit donc d’appeler ce code avec subscriptionUri correspondant a notre adresse de channel et petite astuce, codeHeader doit prendre la valeur de “1” dans le cas d’un Tile et “2” pour un Toast.

msg etant bien sur le flux xml de la notification.

Je dois admettre que cette petite différence de code header est casse pied mais la doc est très clair la dessus :) .

Dans le cas d’un envoi d’information en Raw, une fois votre protocole défini, il vous suffit d’envoyer l’information sans mettre de code header particulier.

Si on prend l’exemple MSDN :

new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

Rien de nous empêche bien sûr d’envoyer des textes en clair ou autre information, quand que les deux parties savent le lire et l’écrire correctement :) .

L’idée est de permettre un transfert simple d’information même quand l’application n’est pas active (car si active, un simple webservice suffit amplement).

Pour les toast, je vous laisse vous reporter a l’image plus haut pour voir a quoi cela ressemble, concernant le changement de tile et l’ajout d’information, voici une illustration:

wp7Tile2

Je n’ai mis que de petit bout de code pour me concentrer sur l’essentiel mais pour ceux n’ayant pas réussi à remettre cela en ordre, voici une classe complète permettant de gérer les abonnements.

public class Notification
{
    public HttpNotificationChannel myChannel;
    public void CreatingANotificationChannel()
    {
        myChannel = HttpNotificationChannel.Find("MyChan");

        if (myChannel == null)
        {
            myChannel = new HttpNotificationChannel("MyChan");
            myChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myChannel_ChannelUriUpdated);
            myChannel.Open();
        }
        else
        {
            Debug.WriteLine("Notification channel URI:" + myChannel.ChannelUri.ToString());
        }
        myChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(myChannel_HttpNotificationReceived);
        myChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myChannel_ErrorOccurred);
        myChannel.BindToShellTile();
        myChannel.BindToShellToast();
    }

    void myChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
    {
        Debug.WriteLine("Notification channel URI:" + e.ChannelUri.ToString());
    }

    void myChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
    {
        switch (e.ErrorType)
        {
            case ChannelErrorType.ChannelOpenFailed:
                // ...
                break;
            case ChannelErrorType.MessageBadContent:
                // ...
                break;
            case ChannelErrorType.NotificationRateTooHigh:
                // ...
                break;
            case ChannelErrorType.PayloadFormatError:
                // ...
                break;
            case ChannelErrorType.PowerLevelChanged:
                // ...
                break;
        }
    }
    void myChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
    {
        if (e.Notification.Body != null && e.Notification.Headers != null)
        {
            System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body);
        }
    }
}

J’ai également mis en place une page web vous permettant d’envoyer des notifications sur un channel que vous lui donnez en paramètre :) .

http://wp7.fr/push/

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: .Net, C#, WP7 Tags: , , ,

Développeur et/ou designer ?

btncourses

La politique de Microsoft avec sa nouvelle gamme de techno est d’offrir un ensemble d’outil permettant une création rapide de logiciel mais également avec une forte personnalisation.

WPF et Silverlight reposent tous deux sur .Net et ce qui nous concerne dans cet article et qui fait leurs forces sur le langage XAML (eXtensible Application Markup Language).

Langage permettant une vrai interaction avec le code métier tout en restant bien séparé (oui oui, c’est possible).

Nous n’en somme plus aux outils qui génèrent des lignes de code (quoi que si on s’enfonce dans le processus d’exécution, on en revient forcement a cela) comme nous avons pu connaitre avec l’ère des WinForms par exemple.

Cette façon de faire, Apple la compris avec Cocoa qui stock ses interfaces dans du xml, Microsoft quand a lui a opté pour enrichir quelque peu tout cela pour en faire du xaml.
J’évoque ce point car au sein de mon travail je côtoie de très proche Cocoa et j’aime les comparer et voir les forces et faiblesses de chacun (De bons points partout !).

Nous le voyons de plus en plus sur l’ensemble des plateformes, ce qui intéresse l’utilisateur n’est plus vraiment la fonctionnalité, entendre par là que cela doit marcher mais que de nos jours c’est une chose implicite (et heureusement nous aurions tendance à dire) et donc que le point central est maintenant la forme du produit.

Son style, son look, son design !

Savoir mettre en avant une fonctionnalité ne passe plus seulement par la mettre dans le manuel de l’application mais justement que ce dernier soit sans intérêt car l’ensemble des interactions homme machine soient les plus logiques et donc naturelles possible.

Un logiciel n’est donc plus créé par une équipe de développeurs mais de designers qui vont la réfléchir et prototyper en mettant en avant l’utilisation, non plus seulement le fonctionnel du produit.

Ensuite seulement, les développeurs vont sortir leurs outils bien à eux et donner à vie à l’application.

Ce processus en deux temps existe depuis toujours mais les choses étant ce qu’elle était, nous nous retrouvions soit avec une application qui fait le café mais ignoble, soit avec un œuvre d’art mais sans aucun intérêt.

Cette époque est révolue et les outils émergent pour que nos métiers deviennent de plus en plus complémentaires.

Ceux qui me connaissent savent que je suis un piètre graphiste, que le design et moi cela fait 3 mais je tente de me soigner depuis quelques temps maintenant, j’aurais même tendance à dire que malgré mon absence de talent artistique, je « pense » design avant de me jeter sur un morceau de code et c’est déjà un bien grand pas pour nous pauvres développeurs !

Bon ce discours, on le connait tous maintenant mais dans la réalité ?

Et bien les designers et autres « artistes » on les cherche encore à nos côtés en entreprise !

Alors il faut également apprendre à se servir de quelques outils nous permettant de devenir plus polyvalent sur nos créations et d’apporter cette petite touche créative sortant tout droit de nos esprits tordu et agencé a coup de if else.

btntutorials

Lancé il y a maintenant quelques mois, le site .Toolbox réclame d’être mieux connu de par les utilisateurs de Blend pour qui c’est leur outil de travail mais également de ceux qui lance Visual Studio donc nous les esprits tordu.

Oui il faut le reconnaitre, Visual Studio gère le fameux xaml et c’est même pratique pour faire une application minimaliste mais si on veut rentrer dans cette nouvelle ère il faut un outil adapté, le fameux Blend.

.Toolbox est organisé comme un site de gamers mais dispense de nombreux cours sur un panel assez large de possibilités, on y gagne des médailles et autres achievements a chaque fois que l’on passe un niveau donc si vous aviez besoin de motivation pour vous lancer dans le design, dur de faire mieux (si si, en le répétant souvent on finit par y croire)

Vous pourrez constater qu’avec bien peu de code, on peut arriver à de fort jolie ET fonctionnel résultat donc maintenant, une fois votre expertise sur Blend dans la poche je vous laisse imaginer la puissance de vos applications :) .

http://www.microsoft.com/design/toolbox/

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz

Un ViewModel mais plusieurs View? merci ObjectDataProvider!

La problématique est toute simple, au sein d’un logiciel, j’ai plusieurs “toolsbox” me servant à modifier mes paramètres, chaque box peut apparaitre X fois sur Y inspecteurs différents mais au final tous sont reliées au même modèles.

Face au fait que beaucoup de données sont traitées, même si toutes viennent du même modèle et donc “n’existe” qu’une fois, il n’en reste pas moins que chaque instanciation de mes ViewModel implique de jouer son rôle de proxy pour ces données, mais pas une fois, plusieurs fois pour offrir les mêmes données?!

Donc oui le pattern MVVM indique que comme on tape sur le même model, chaque viewModel offre ce qu’il faut à sa vue et puis basta, et bien dans mon cas cela ne me suffit pas.

Deux solutions sont dont offertes:

  • Instancier mon unique DataContext en codebehind lors de la création de mes vues
  • Trouver un moyen pour que la view s’occupe elle-même de récupérer une instance unique de son ModelView

Ayant pris l’habitude d’utiliser blend, car blend c’est vraiment la vie (une petite pensée pour Dick Lantim qui aura essayé pendant deux mois de me convertir sans réussir…je regrette de ne pas avoir été un bon élève!), j’ai donc opté pour la seconde solution.

L’idée est de remplacer le code suivant qui permet l’instanciation du DataContext par un autre permettant de juste récupérer une instance unique du DataContext.

<UserControl.DataContext>
        <ModelView:BoxCamera/>
</UserControl.DataContext>

L’idée va être de passer par un ObjectDataProvider que nous allons déclarer une fois pour toute dans le App.xaml:

<Application.Resources>
    <ObjectDataProvider MethodName="GetInstance" ObjectType="{x:Type ModelView:BoxCamera}" x:Key="BoxCamera"/>
</Application.Resources>

Et notre ModelView va maintenant passer en mode Singleton pour renvoyer une unique instance qui va donc nous permettre de soulager un peu l’application en évitant de créer plusieurs ModelView quand un seul est nécessaire.

private static BoxCamera _instance;
        public static BoxCamera GetInstance()
        {
            if (_instance != null) return _instance;
            else
            {
                _instance = new BoxCamera();
                return _instance;
            }
        }
private BoxCamera() {}

Il nous reste plus qu’à faire notre binding de DataContext dans notre View et ensuite son utilisation est totalement transparente:

DataContext="{DynamicResource BoxCamera}"

Et voilà, plusieurs vue, un seul DataContext instancié donc dans certains cas le gain est vraiment appréciable :) .

Ce cas est assez particulier car repose sur un besoin que je viens d’avoir mais il faut noter que l’ObjectDataProvider  est vraiment pratique pour gérer un peu plus finement les créations de DataContext au sein de nos vues.

Par exemple, nous pouvons instancié un ModelView précis:

<ObjectDataProvider  ObjectType="{x:Type ModelView:BoxCamera}" x:Key="BoxCamera"/>

Mais dans le cas où nous aimerions passer des paramètres a notre constructor?

<ObjectDataProvider MethodName="GetInstance" ObjectType="{x:Type ModelView:BoxCamera}" x:Key="BoxCamera">
    <ObjectDataProvider.ConstructorParameters>
        <system:String>Stumpy</sys:system>
    </ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>

Vous avez besoin d’une donnée précise dans un morceau de votre application mais bon, pour X raison le ViewModel de cette vue ne contient pas la donnée et son ajout est peu pratique/élégant?
Aucun soucis car il vous suffit de récupérer notre ressource déclarée plus haut comme source et vous binder dessus:

<TextBlock Text="{Binding Path=FocaleValue, Source={StaticResource BoxCamera}}"/>

Bon il faut avouer, ce n’est pas super propre comme façon de faire mais disons que cela peut dépanner dans certains cas.

Un ViewModel un peu long à charger?
Aucun soucis, en settant IsAsynchronous a true, notre ViewModel est chargé en async donc on soulage encore un peu nos vues lors des phases de lancement.

Et nous pouvons sans doute lui trouver encore d’autres utilités :) .

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: .Net, Blend, C#, WPF Tags: , , , ,

OData, Comment lire un flux?

Dans l’article précèdent, nous avons mis en place un WebService offrant un accès sur une base de donnée par le biais du protocole OData.
Nous avons vu qu’il était possible de lire le flux par le biais du logiciel LinqPad mais également un simple navigateur.
Il serait intéressant maintenant de lire cela dans une application directement, non?

Je vous invite donc à reprendre votre solution de test fait dans l’article précèdent et y ajouter un projet de type WPF application.

clip_image002

Nous allons ensuite faire une petite interface qui va juste nous permettre d’avoir un rendu visuel, pour le cote sexy de l’application on repassera plus tard ;) .

clip_image003

Pour vous faire gagner un peu de temps, voici le code xaml de la fenêtre :

<Grid>
    <Button Content="Refresh" Click="Button_refresh" Margin="214,0,213,258" />
    <ListBox x:Name="myList" Margin="0,0,295,0" />
</Grid>

Nous avons donc une ListBox et un Button, il reste maintenant à offrir une source de donnée à notre superbe application.

Pour cela, on ajoute une référence vers notre WebService comme d’habitude :
Clic droit sur References dans le projet puis ajouter un « service reference »
Notre service étant dans notre solution, il vous suffit de faire « Discover » puis de lui donner un petit nom, par exemple « MyService »

clip_image001

Rien de bien nouveau en soit, voyons maintenant comment remplir notre listbox.

Notre bouton de refresh étant brancher sur un évènement clic, il nous suffit de rajouter la méthode suivante en code-behind de notre fenêtre :

private void Button_refresh(object sender, RoutedEventArgs e)
{
    this.db = new MyService.NORTHWNDEntities(new Uri("http://localhost:26162/WcfDataService1.svc"));
    var query = from c in db.Contacts select c;
    this.Contact = new DataServiceCollection<MyService.Contacts>(query);
    this.myList.ItemsSource = Contact;
}

Pensez à ajouter les propriétés de classe :

MyService.NORTHWNDEntities db = null;
DataServiceCollection<MyService.Contacts> Contact = null;

Mais aussi à remplacer le port par celui sur lequel tourne votre service !

La première ligne est là pour nous permettre de récupérer un context sur notre webService et nous allons ensuite nous en servir pour l’interroger.
Dans mon cas, je souhaite récupérer l’ensemble des contacts donc ma requête reste assez simple et je la passe ensuite dans le constructeur de ma DataServiceCollection.
Il me reste plus qu’à donner comme source à ma liste la collection en question :) .
Je vous laisse essayer et constater que « normalement » tout marche comme prévu, quoique l’affichage de notre listbox n’est pas très agréable à voir.

Un petit ajout dans le xaml semble utile, remplacer votre listbox par celui-là puis relancer

<ListBox x:Name="myList" Margin="0,0,295,0">
    <ListBox.ItemTemplate>
        <DataTemplate>
             <TextBlock Text="{Binding ContactName}" />
        </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

Déjà un bon résultat pour si peu de travail.
Une problématique qui peut se poser est la pagination des données, oui dans notre cas la liste des contacts n’est pas énorme mais dans le cas où elle contiendrait des milliers de données ?
Hmm…Un peu lourd de tout récupérer d’un coup peut-être ?

Retournons dans notre webservice et essayons de faire un système permettant de n’envoyer seulement que N éléments à la fois et s’arranger pour envoyer N de plus sur demande.
On se souvient avoir mis la ligne

config.SetEntitySetAccessRule("Contacts", EntitySetRights.All);

Ajoutons cette petite ligne à la suite :

config.SetEntitySetPageSize("Contacts", 42);

Et…voilà, notre système de pagination est fini, mon café n’a même pas eu le temps de refroidir…
Je vous laisse relancer votre client et constater que maintenant on ne récupère plus que les 42 premiers éléments de notre table, ajoutons donc un système pour récupérer la suite !

Retour dans le xaml pour y ajouter un petit bouton dont voici le xaml a glissé dans votre fenêtre :

<Button Content="Next" Click="Button_Next" Margin="314,0,112,258" />

Allons maintenant remplir le code de l’event sur lequel pointe ce bouton:

private void Button_Next(object sender, RoutedEventArgs e)
{
    if (this.Contact == null || this.Contact.Continuation == null)
        return;
    this.Contact.Load(this.db.Execute<MyService.Contacts>(this.Contact.Continuation.NextLinkUri));
}

Donc un petit check pour eviter de planter dans le cas ou notre liste n’aurait pas été chargées au préalable
Et ensuite, on charge la suite de notre collection, pour cela un petit appel à notre context en lui indiquant que l’on veut récupérer « la suite ».

Si vous regardez la valeur de NextLinkUri vous y verrez une simple uri avec un argument indiquant « quoi renvoyer »
Encore une fois, rien de bien sorcier, l’ensemble du process est géré pour nous.

Je vous laisse vous amuser avec votre nouveau bouton pour voir ce remplir votre liste de contact et de mon cote je garde encore mon café chaud pour le moment !

Jusqu’à la, nous avons fait de la lecture de base, on se souvient d’avoir laissé le service ouvert en écriture pour la table Contacts donc essayons d’y ajouter un élément ;) .
Encore une fois, voici un petit morceau de xaml à ajouter dans votre fenêtre :

<Button Content="Add" Click="Button_Add" Margin="419,0,12,258" />

Et voici le code allant avec notre event d’ajout:

private void Button_Add(object sender, RoutedEventArgs e)
{
    if (this.Contact == null)
        return;
    this.Contact.Add(new MyService.Contacts()
    {
        CompanyName = "42",
        ContactName = "Marvin"
    });
    db.SaveChanges();
}

Un petit check pour la forme puis on ajoute un contact dans notre collection.
Et puis on demande au context de nous sauvegarder les changements.

Voilà, notre mini gestionnaire de contact est terminé, je vous laisse le décorer pendant que je déguste mon café.

La version en Silverlight reposerait sur le même code, juste noter que l’ensemble des appels au webservice seraient asynchrones comme toujours en Silverlight

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • email
  • Live
  • MySpace
  • PDF
  • Slashdot
  • Technorati
  • Twitter
  • Yahoo! Buzz
Categories: .Net, C# Tags: , , , ,