Création de nouvelles pages et navigation sur Windows Phone 7

Ceci est le sixième billet d’une série sur Windows Phone 7 dans laquelle je construis une application permettant de surveiller la disponibilité de vélos des stations Vélib’ à Paris. Pour rappel, voici la table de matières:

  1. Introduction et installation des outils
  2. Création d’une application et utilisation du contrôle Bing Maps
  3. Le GPS et les services de géolocalisation
  4. Consommation d’un service OData
  5. Ajout de punaises sur une carte Bing Maps
  6. Création de nouvelles pages et navigation
  7. Création de vignettes sur la page d’accueil

Un modèle de programmation Web

Screenshot 2

Vous avez surement remarqué l’absence de fenêtres dans notre application Windows Phone 7. Cela aurait pu vous marquer, notamment si vous êtes habituées au développement sur environnements desktop, voire aussi sur des anciennes versions de Windows Mobile.

Si je devais faire un parallèle entre le développement sur Windows Phone 7 et une autre plateforme, je me verrais obligé de le comparer au développement Web—en tout cas pour ce qui est des applications Silverlight ; les application XNA sont une toute autre histoire.

En effet, si vous examinez le code généré dans le fichier App.xaml.cs vous trouverez qu’au démarrage de l’application on commence par déclarer comme élément racine un objet de type PhoneApplicationFrame. C’est dans ce frame que vont être affichées par la suite vos pages, qui dérivent de la classe PhoneApplicationPage. Le similitudes ne se limitent pas au frame et aux pages. Vous verrez qu’on retrouvera des concepts tels que les URIs, les hyperliens, etc.

Une nouvelle page

Hier nous avons permis à l’utilisateur d’afficher des stations sur sa carte. Il est même capable d’appuyer sur l’une de ces dernières et, de notre côté, nous savons identifier la station qu’il a sélectionnée, mais il nous manque quelque chose pour en afficher les détails.

Ajoutez à votre projet un nouvel élément. Sélectionnez une nouvelle Windows Phone Portrait Page parmi les templates Silverlight for Windows Phone.

Add New Item - UnVelo.Wp7

La page créée ressemble à la page principale lorsque nous avons démarré le projet.

Cette fois-ci, nous allons travailler sur le modèle par défaut en remplaçant certaines valeurs et en le complétant avec les contrôles nécessaires pour obtenir un affichage comme celui sur la capture au début de ce billet.

Commençons par modifier la partie du haut :

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" Text="UN VELO.FR"
               Style="{StaticResource PhoneTextNormalStyle}"/>
    <TextBlock x:Name="PageTitle" Text="{Binding Number, StringFormat='Station {0}'}"
               Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

Le nom de l’application sera une valeur constante, en revanche, le titre devra afficher le numéro de station. Nous utilisons donc une expression de binding pour afficher la propriété Number de la classe Station. Petite nouveauté “Mango” : comme on utilise enfin Silverlight 4, nous avons accès à la propriété StringFormat de l’expression de binding, ce qui nous permet de personnaliser un peu le texte affiché sans passer par des convertisseurs ou des piles de TextBlocks.

En raison de ce qui semblerait être un bug dans le contrôle Bing Maps, je n’ai pas pu placer tous mes contrôles dans le ContentPanel fourni pour cet effet. J’ai donc modifié le LayoutRoot :

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid.Resources>
        <local:StationConverter x:Key="StationConverter" />
    </Grid.Resources>
<!-- ... -->

En y ajoutant une ligne, j’ai pu placer la carte juste au dessus du ContentPanel :

<map:Map Margin="12,0,12,0" Grid.Row="1" Grid.ColumnSpan="2" Height="250"
        CredentialsProvider="{StaticResource BingMapsKey}" ZoomLevel="16"
        Center="{Binding Converter={StaticResource StationConverter}}">
    <map:MapItemsControl x:Name="pins"
        ItemsSource="{Binding Converter={StaticResource StationConverter}}">
        <map:MapItemsControl.ItemTemplate>
            <DataTemplate>
                <map:Pushpin Location="{Binding Location}" />
            </DataTemplate>
        </map:MapItemsControl.ItemTemplate>
    </map:MapItemsControl>
</map:Map>

<!--ContentPanel - place additional content here-->
<StackPanel x:Name="ContentPanel" Grid.Row="2" Margin="12,12,12,0">
    <TextBlock Text="{Binding Name}"
               FontFamily="{StaticResource PhoneFontFamilySemiBold}"
               FontSize="{StaticResource PhoneFontSizeLarge}"
               Foreground="{StaticResource PhoneAccentBrush}" />
    <TextBlock Style="{StaticResource PhoneTextLargeStyle}"
      Text="{Binding AvailableBikes, StringFormat='Vélos disponibles : {0}'}" />
    <TextBlock Style="{StaticResource PhoneTextLargeStyle}"
      Text="{Binding FreeSpaces, StringFormat='Places disponibles : {0}'}" />
</StackPanel>

Le code ci-dessus est moins complexe qu’il ne parait. Certes, la présence d’un converter dans les bindings vous perturbe certainement un peu et le rendu fait par le designer est assez décevant :

ViewHolder2

Tous les bindings ont été faits en supposant qu’un objet de type Station se trouve dans le DataContext de la page. Or nous n’avons pas encore défini de station, donc rien ne s’affiche.

On a besoin d’une station !

Naviguer entre les pages

Revenons sur la page principale ; plus spécifiquement, dans le gestionnaire de l’évènement Tap des punaises :

private void OnStationTap(object sender, GestureEventArgs e)
{
    var station = (sender as Pushpin).DataContext;
}

Nous avons une station dont nous voulons afficher les détails.

Pas question ici de créer une nouvelle instance de la classe que nous venons de créer. Je vous rappelle que nous sommes dans un modèle type Web et nous allons tout simplement naviguer entre les pages comme nous l’aurions fait avec des documents HTML.

Pour cela, nous avons à notre disposition un NavigationService qui est accessible par la propriété homonyme de vos pages. Ce service propose une méthode Navigate qui prend en paramètre un URI relatif vers la destination :

private void OnStationTap(object sender, GestureEventArgs e)
{
    var station = (sender as Pushpin).DataContext;

    NavigationService.Navigate(new Uri("/DetailsPage.xaml", UriKind.Relative));

    // Dans la version ci-dessous on spécifie l'assembly (UnVelo.Wp7)
    // Cela peut-être utile si vos pages se trouvent dans un assembly
    // différent de celui en cours d'exécution
    // NavigationService.Navigate(new Uri("/UnVelo.Wp7;component/DetailsPage.xaml", UriKind.Relative));
}

Le code ci-dessus (les deux versions) produit l’effet désiré : le téléphone change de page et affiche celle que nous avons préparée plus haut. De plus, la page principale a été placée sur la pile de navigation, ce qui nous permet d’y retourner via le bouton Précédent.

En revanche, le code ne fait que ça : passer la page ; et comme nous n’instancions pas la page nous-mêmes, il n’y a, a priori pas de moyen de passer des données via des propriétés de la page comme on a l’habitude de le faire sous d’autres plateformes.

Transmission de données entre les pages

Il y a deux manières de passer des données en mémoire d’une page à une autre : la query string (comme dans le Web) et l’état courant du PhoneApplicationService.

Comme dans une page web, on peut passer des informations dans l’URI de la page appelée, par exemple, dans la page principale on écrit :

private void OnStationTap(object sender, GestureEventArgs e)
{
    var pin = ((sender as Pushpin).DataContext as Pin);

    var uri = string.Format("/DetailsPage.xaml?id={0}", pin.Station.Number);
    NavigationService.Navigate(new Uri(uri, UriKind.Relative));
}

Et dans la page détails on peut récupérer la valeur avec le code suivant :

public override void OnNavigatedTo(NavigationEventArgs e)
{
    var number = NavigationContext.QueryString["id"];

    // ...

    base.OnNavigatedTo(e);
}

La méthode OnNavigatedTo de la page est appelée lorsque l’on arrive sur une page—son opposé est OnNavigatedFrom, qui est appelée juste avant que l’on quitte une page. Dans cette méthode on pourrait récupérer les différentes valeurs qui ont été passées dans la query string pour les assigner aux contrôles de la page ou pour effectuer des data bindings.

Toutefois, dans l’exemple qui nous concerne, nous voulons passer bien plus d’informations que juste le numéro de station, et nous avons toutes ces informations encapsulées dans une instance de la classe Station. De plus, il peut exister des cas où les données qui doivent être partagées entre les pages ne peuvent pas être transformées en chaine de caractères pour être concaténées à l’URI de la page. Pour ces cas-là, la classe PhoneApplicationService mantient un état courant dans lequel on peut stocker des objets pour les partager entre plusieurs pages :

private void OnStationTap(object sender, GestureEventArgs e)
{
    var pin = ((sender as Pushpin).DataContext as Pin);

    PhoneApplicationService.Current.State["currentStation"] = pin.Station;

    NavigationService.Navigate(new Uri("/DetailsPage.xaml", UriKind.Relative));
}

Les lignes ci-dessus enregistrent dans un emplacement de l’état courant de l’application, que l’on appelle arbitrairement currentStation, la station contenue dans le DataContext de la punaise qui a été appuyée par l’utilisateur. Du côté de la page de détails, quelques lignes suffiront à récupérer cet objet pour afficher les informations qu’il contient :

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    object station;

    if (PhoneApplicationService.Current.State.TryGetValue("currentStation", out station))
    {
        this.DataContext = station;
    }

    base.OnNavigatedTo(e);
}

On aurait pu se contenter de faire tout simplement l’assignation :

this.DataContext = PhoneApplicationService.Current.State["currentStation"];

Mais l’utilisation de la méthode TryGetValue maintenant nous permettra de prévoir des cas où il n’y a pas de valeur pour la clé currentStation à l’avenir.

Grâce aux bindings que nous avions déclarés lorsque nous avons créé la page de détails, le fait d’assigner un objet de type Station à son DataContext suffit à afficher la page comme on le voulait.

Details_page

Si vous essayez d’exécuter le code il vous manquera cependant la classe StationConverter que nous avons utilisée pour simplifier certains bindings :

public class StationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var station = value as Station;

        if (null == station)
        {
            return value;
        }

        if (typeof(GeoCoordinate) == targetType)
        {
            return new GeoCoordinate((double)station.Latitude, (double)station.Longitude);
        }
        else if (typeof(IEnumerable) == targetType)
        {
            return new object[] { new Pin { Station = station } }.AsEnumerable();
        }

        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Nous approchons de la fin de la série. Maintenant que nous avons réussi à afficher les détails d’une station dans une page, nous allons profiter d’une des nouveautés de “Mango” qui nous permettra de modifier, à partir du code uniquement, des vignettes sur la page d’accueil pour y afficher, par exemple, le nombre de vélos disponibles dans une station. Mais ce code-là, on le verra demain.

Publicités

Ajout de punaises sur une carte Bing Maps

Ceci est le cinquième billet d’une série sur Windows Phone 7 dans laquelle je construis une application permettant de surveiller la disponibilité de vélos des stations Vélib’ à Paris. Pour rappel, voici la table de matières:

  1. Introduction et installation des outils
  2. Création d’une application et utilisation du contrôle Bing Maps
  3. Le GPS et les services de géolocalisation
  4. Consommation d’un service OData
  5. Ajout de punaises sur une carte Bing Maps
  6. Création de nouvelles pages et navigation
  7. Création de vignettes sur la page d’accueil

On a besoin de punaises

Hier nous nous sommes arrêtés sur une liste stations. Chaque station est représentée par un objet de type Station qui contient des propriétés telles que le numéro de station, son adresse, le nombre de vélos et de places disponibles, mais surtout, ses coordonnées géographiques.

La prochaine étape sera donc d’utiliser ces informations pour afficher des punaises sur la carte de la page principale qui donneront un aperçu de l’état de chaque station et qui nous permettront d’accéder à la page de détails de celles-ci.

Pour afficher des punaises sur une carte, vous allez utiliser des calques. Ces calques dérivent de MapLayer et supportent des éléments d’à peu près n’importe quel type:

custom_pins

Dans notre cas, le Pushpin fourni dans l’assembly Bing Maps suffira largement. Ce contrôle possède deux propriétés qui nous intéressent :

Taj_Mahal

  • Content : est une propriété héritée de ContentControl qui permet à la classe Pushpin d’afficher à peu près n’importe quel contenu.
  • Location : est de type GeoCoordinate et représente les coordonnées géographiques de la punaise qui serviront à la positionner sur la carte.
<map:Pushpin Content="Taj Mahal" Location="27.172222,78.042476" />

Cependant, notre modèle de données, la Station, ne correspond pas tout à fait à ce qui est attendu par la classe Pushpin. Avant de continuer, vous aurez donc besoin d’un modèle qui représentera les stations sur la carte. Créez la classe Pin dans votre projet :

public class Pin
{
    public Station Station { get; set; }

    public string Label { get { return this.Station.Number.ToString(); } }

    public GeoCoordinate Location
    {
        get
        {
            return new GeoCoordinate(
                (double)this.Station.Latitude,
                (double)this.Station.Longitude);
        }
    }
}

Transformez maintenant votre collection de Stations en une collection de Pins :

private void GetStationsInRectangleCallbak(IAsyncResult result)
{
    var stations = this._repository.EndExecute<Station>(result);

    var p = from s in stations
            select new Pin { Station = s };

    Dispatcher.BeginInvoke(
        new Action<IEnumerable>((pins) => pinLayer.ItemsSource = pins), p);
}

Et un calque pour afficher le tout

Dans le code ci-dessus, nous avons transformé les stations et assigné cette nouvelle collection au calque de type MapItemsControl qui hébergera les punaises.

<map:Map x:Name="Map"
    CredentialsProvider="{StaticResource BingMapsKey}"
    ZoomBarVisibility="Visible" ZoomLevel="16"
    ViewChangeEnd="OnViewChangeEnd">
    <map:MapItemsControl x:Name="pinLayer">
        <map:MapItemsControl.ItemTemplate>
            <DataTemplate>
                <map:Pushpin Location="{Binding Location}"
                             Content="{Binding Label}"
                             Tap="OnStationTap" />
            </DataTemplate>
        </map:MapItemsControl.ItemTemplate>
    </map:MapItemsControl>
</map:Map>

MapItemsControl qui expose, entre autres, les propriétés ItemsSource et ItemTemplate qui nous permettent de spécifier les éléments à afficher et le template à utiliser pour leur rendu à l’écran, respectivement. Dans l’exemple ci-dessus, chaque punaise sera représentée par un Pushpin dont les propriétés sont liées à celles du modèle créé à l’étape précédente. De plus, la méthode OnStationTap sera appelée lorsque l’on appuie sur les repères :

private void OnStationTap(object sender, GestureEventArgs e)
{
    var station = ((sender as Pushpin).DataContext as Pin).Station;
}

Nous savons que c’est un objet de type Pushpin qui appelle la méthode et que son DataContext est de type Pin. Il ne reste plus qu’à appeler la propriété Station de ce dernier type pour obtenir les information de la station que l’utilisateur a choisi.

Lundi nous passerons cette station à une nouvelle page qui sera chargée d’afficher ses détails.

Consommation d’un service OData avec Windows Phone 7 “Mango”

Ceci est le quatrième billet d’une série sur Windows Phone 7 dans laquelle je construis une application permettant de surveiller la disponibilité de vélos des stations Vélib’ à Paris. Pour rappel, voici la table de matières:

  1. Introduction et installation des outils
  2. Création d’une application et utilisation du contrôle Bing Maps
  3. Le GPS et les services de géolocalisation
  4. Consommation d’un service OData
  5. Ajout de punaises sur une carte Bing Maps
  6. Création de nouvelles pages et navigation
  7. Création de vignettes sur la page d’accueil

OData

odataMaintenant que votre application est capable de localiser le téléphone et de centrer la carte sur sa position, il est temps de rechercher les stations Vélib’ se trouvant à proximité. Pour cela nous allons utiliser un service OData qui expose des informations sur les vélos de la ville de Paris.

Note : malheureusement, cette pratique n’est pas exactement bien vue par les fournisseurs du service, donc il est possible que dans l’avenir ces instruction ne soient plus valables.

Tout d’abord, qu’est-ce qu’OData ? Il s’agit d’un protocole ouvert pour le partage de données. Il permet d’exposer des jeux de données aux formats ATOM (XML) ou JSON se basant sur une architecture REST. Je ne rentrerai pas dans les détails, mais je vous laisserai visiter le site officiel si vous voulez en savoir plus.

J’ai choisi une source de données OData parce qu’il s’agit d’un protocole léger et facile à consommer, notamment avec l’inclusion dans les Windows Phone Developer Tools 7.1, que je vais continuer à appeler les outils “Mango”, d’un client OData.

Le client OData

Commençons donc par ajouter une référence au service OData :

Add Service Reference

Voilà, c’est fini !

Stations Vélib’ à proximité

Le client en place, il ne reste plus qu’à récupérer les stations Vélib’ à proximité de l’utilisateur.

Si vous regardez la description du service OData de près :

<FunctionImport Name="GetStationsInRectangle" EntitySet="Stations"
                ReturnType="Collection(UnVelo.Station)" m:HttpMethod="GET">
  <Parameter Name="point1" Type="Edm.String" Mode="In" />
  <Parameter Name="point2" Type="Edm.String" Mode="In" />
</FunctionImport>

Vous remarquerez la présence d’une fonction qui retourne les stations présentes dans un rectangle. Ce rectangle est défini par deux points : le coin nord-ouest et le coin sud-est.

Comme nous souhaitons récupérer la liste de stations lorsque la carte affichée change (déplacement, changement de zoom), vous allez vous abonner à l’évènement ViewChangeEnd, qui sera déclenché une fois que le déplacement ou le changement de zoom est fini :

<map:Map x:Name="Map"
    CredentialsProvider="{StaticResource BingMapsKey}"
    ZoomBarVisibility="Visible" ZoomLevel="17"
    ViewChangeEnd="OnViewChangeEnd" />

Dans le gestionnaire de l’évènement, vous allez utiliser un StationRepository qui a été créé automatiquement par Visual Studio à l’étape précédente, pour lancer un appel asynchrone sur la fonction GetStationsInRectangle.

private readonly string GetStationsInRectangleTemplate = "GetStationsInRectangle?point1='{0}'&point2='{1}'";

private GeoCoordinateWatcher _gcw;
private StationRepository _repository;

public MainPage()
{
    InitializeComponent();

    this._gcw = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
    this._gcw.MovementThreshold = 20;
    this._gcw.PositionChanged += this.OnPositionChanged;

    this._repository = new StationRepository(new Uri("http://unvelo.fr/api/v1/"));

    this.Loaded += this.OnPageLoaded;
}

private void OnViewChangeEnd(object sender, MapEventArgs e)
{
    this._repository.BeginExecute<Station>(
        new Uri(
            string.Format(GetStationsInRectangleTemplate, Map.BoundingRectangle.Northwest, Map.BoundingRectangle.Southeast),
            UriKind.Relative),
        this.GetStationsInRectangleCallbak,
        null);
}

Le client OData créé par Visual Studio supporte uniquement les appels asynchrones dans le but d’éviter des exécutions d’appels longs sur le thread de l’interface graphique, étant donné que ceci dégraderait l’expérience utilisateur. Vous devrez donc créer une méthode callback qui sera appelée à la fin de l’exécution asynchrone pour traiter le résultat de celle-ci :

private void GetStationsInRectangleCallbak(IAsyncResult result)
{
    var stations = this._repository.EndExecute<Station>(result);
}

Vous pouvez vérifier que des stations sont effectivement retournées grâce au débuggeur de Visual Studio. Demain nous les convertirons en punaises à afficher sur la carte. D’ici là, vous avez des données avec lesquelles vous pouvez vous amuser. Si vous avez un peu d’expérience avec Silverlight ou WPF, n’hésitez pas à essayer d’afficher ces données par binding sur différents contrôles.

Le GPS et les services de géolocalisation

Ceci est le troisème billet d’une série sur Windows Phone 7 dans laquelle je construis une application permettant de surveiller la disponibilité de vélos des stations Vélib’ à Paris. Pour rappel, voici la table de matières:

  1. Introduction et installation des outils
  2. Création d’une application et utilisation du contrôle Bing Maps
  3. Le GPS et les services de géolocalisation
  4. Consommation d’un service OData
  5. Ajout de punaises sur une carte Bing Maps
  6. Création de nouvelles pages et navigation
  7. Création de vignettes sur la page d’accueil

Accéder à la position actuelle du téléphone

On voudrait, lorsque l’application se lance et lorsque l’utilisateur bouge, que la carte que nous avons ajoutée hier soit centrée sur leur position courante. Pour cela nous allons utiliser des classes du namespace System.Device.Location et, plus spécifiquement, la classe GeoCoordinateWatcher.

Cette classe nous permet d’obtenir la position du téléphone en utilisant plusieurs sources : les bornes WiFi à proximité, les tours cellulaires et, bien sûr, le GPS. C’est pour cette raison que dans le titre du billet je parle de GPS et des services de géolocalisation.

Pour lancer la détection de la position courante de l’utilisateur dans notre page principale, nous allons écrire un peu de C#. Ouvrez le fichier MainPage.xaml.cs pour ajouter une instance de GeoCoordinateWatcher à votre page :

private GeoCoordinateWatcher _gcw;

// Constructor
public MainPage()
{
    InitializeComponent();

    this._gcw = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
    this._gcw.MovementThreshold = 20;
    this._gcw.PositionChanged += this.OnPositionChanged;

    this.Loaded += this.OnPageLoaded;
}

Vous aurez remarqué que je demande au GeoCoordinateWatcher de récupérer la position du téléphone avec le plus de précision possible. Ceci parce que j’ai besoin de lui montrer des information qui sont très liées à sa position exacte. Si mon application avait seulement besoin de connaitre la position approximative de l’utilisateur, j’aurais passé la valeur GeoPositionAccuracy.Normal au constructeur, ce qui permet au téléphone de mieux gérer ses ressources. J’ai aussi spécifié la valeur minimale, en mètres, que la position du téléphone doit changer pour qu’un évènement de changement de position soit levé. Ceci évitera que le logiciel rafraichisse inutilement ses données trop souvent.

J’ai attendu que la page soit totalement chargée avant de démarrer le service de localisation :

private void OnPageLoaded(object sender, RoutedEventArgs e)
{
    this._gcw.Start();
}

void OnPositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    this.Map.Center = e.Position.Location;
}

Lorsque la position change et que la méthode OnPositionChanged est appelée, je récupère la position actuelle et j’en fait le centre de la carte que j’ai ajoutée hier à la page. D’ailleurs, le code du contrôle Bing Maps a changé un peu depuis hier :

<map:Map x:Name="Map"
    CredentialsProvider="{StaticResource BingMapsKey}"
    ZoomBarVisibility="Visible" ZoomLevel="17"/>

Le simulateur

Si vous lancez votre application dans l’émulateur, vous constaterez rapidement que son comportement a changé. La carte est désormais automatiquement centrée sur le campus de Microsoft à Redmond :

Windows Phone Emulator (3)

Ceci s’explique par le nouveau simulateur GPS installé avec les outils “Mango”. Pour y accéder, cliquez sur le double chevron dans la boite à outils de l’émulateur, puis sur l’onglet Location de la fenêtre qui s’ouvre.

Additional Tools

Tant que le bouton Live de nouvelle fenêtre est activé (gris foncé), chaque clic sur la carte placera une punaise qui deviendra la position actuelle communiqué aux services de géolocalisation du téléphone.

Vous pouvez utiliser la souris pour naviguer sur la carte et les contrôles de zoom pour obtenir plus ou moins de précision. Vote application étant à l’écoute des changements de position des services de géolocalisation, elle devrait centrer la carte sur une nouvelle position à chaque fois que vous cliquez sur la carte du simulateur. Pour préparer l’image ci-dessous, j’ai effectué une recherche avec les mots clés “Paris, France”, j’ai ensuite zoomé sur l’Ile de la Cité et cliqué près de Notre-Dame pour y placer une punaise et centrer le téléphone sur cette nouvelle position.

Additional Tools (2)

Je vous laisse étudier plus en détail les services de géolocalisation et vous amuser avec le simulateur si vous le souhaitez. Vous pouvez essayer de créer des parcours qui simuleront une personne qui se déplace, par exemple.

Demain nous allons chercher les stations Vélib’ qui se trouvent à proximité du téléphone.

Création d’une application et utilisation du contrôle Bing Maps

Ceci est le deuxième billet d’une série sur Windows Phone 7 dans laquelle je construis une application permettant de surveiller la disponibilité de vélos des stations Vélib’ à Paris. Pour rappel, voici la table de matières:

  1. Introduction et installation des outils
  2. Création d’une application et utilisation du contrôle Bing Maps
  3. Le GPS et les services de géolocalisation
  4. Consommation d’un service OData
  5. Ajout de punaises sur une carte Bing Maps
  6. Création de nouvelles pages et navigation
  7. Création de vignettes sur la page d’accueil

Description de l’application

Hier, pressé de vous faire installer les outils, j’ai oublié de vous présenter l’application elle-même !

Il s’agit d’une application très simple, permettant de surveiller la disponibilité des Vélib’s à Paris. Pour ceux qui ne connaissent pas Vélib’, il s’agit d’un réseau de stations, permettant la location de courte durée de vélos dans la capitale.

Notre application aura donc deux écrans :

Screenshot 1Screenshot 2

Le premier permet d’apercevoir, sur une carte qui occupe l’écran entier, les stations à proximité de l’utilisateur. Le deuxième sera accessible lorsque l’on appuie sur une station sur la carte ou depuis l’écran d’accueil.

Création du projet

Nous allons commencer par créer un nouveau projet.

New Project

Sélectionnez un projet de type Windows Phone Application dans la catégorie Silverlight for Windows Phone. J’ai appelé mon projet UnVelo.Wp7, mais vous êtes libres d’appeler le vôtre comme vous le souhaitez.

Comme j’avais prévenu, j’aurai besoin de fonctionnalités disponibles uniquement dans la nouvelle version du système d’exploitation. Choisissez donc les outils “Mango” ou Windows Phone 7.1 :

New Windows Phone Application

WindowClipping Votre nouveau projet contient déjà un certain nombre de fichiers :

  • App.xaml et App.xaml.cs contiennent du code relatif à l’application dans sa globalité, par exemple, des gestionnaires d’évènements ou, dans quelques instants, des ressources globales.
  • ApplicationIcon.jpg, Background.jpg et SplashScreenImage.jpg sont des images utilisées par le téléphone pour l’icône de l’application, la vignette de l’écran d’accueil et au démarrage de l’application. Je ne rentrerai pas dans le détail pour le moment, mais je vous encourage à jouer avec pour voir comment elles se comportent.
  • MainPage.xaml a été configurée dans App.xaml comme étant la page de démarrage de notre application, c’est donc ici que nous allons commencer.

ViewHolder

La page contient un certain nombre d’éléments par défaut. Ceux-ci permettent au développeur d’indiquer le nom de l’application, le titre de page et, dans une grille appelée ContentPanel, d’ajouter le contenu qu’il souhaite. Dans notre cas, cette page ne nous convient pas du tout, nous allons donc tout supprimer et ajouter notre plan.

Le contrôle Bing Maps

Pour ajouter un plan dans la page principale, nous allons utiliser le contrôle Bing Maps pour Silverlight fourni avec Windows Phone. Pour cela, vous devez ajouter une référence vers l’assembly Microsoft.Phone.Controls.Maps :

Add Reference

Ensuite, pour utiliser le contrôle dans le code XAML, il faut donner un alias au namespace Microsoft.Phone.Controls.Maps dans le fichier MainPage.xaml :

<phone:PhoneApplicationPage
    x:Class="UnVelo.Wp7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:map="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

Ce qui nous permettra enfin d’ajouter le contrôle à notre page :

<Grid x:Name="LayoutRoot" Background="Transparent">
    <map:Map />
</Grid>

Un petit Ctrl+F5 compilera et lancera l’émulateur pour que nous puissions enfin voir notre application pour la première fois :

Windows Phone Emulator

En l’état, vous ne pouvez pas faire grand-chose avec l’application. Vous pouvez tout de même utiliser un doigt pour déplacer la carte, faire un “double-clic” en appuyant deux fois rapidement pour zoomer et quitter l’application à l’aide du bouton Précédent de l’émulateur. Si vous avez un écran tactile, vous pourrez aussi tester des gestes comme le “pincement” pour zoomer.

Vous avez surement remarquée aussi la présence d’un message au milieu du contrôle, vous indiquant que vous n’avez pas fourni d’information d’identification et vous invitant à créer un compte développeur.

Ce compte peut être créé gratuitement sur le site Bing Maps Account Center et sera lié à un Live Id. Sur ce site vous pourrez créer une nouvelle “clé” pour l’utilisation des APIs Bing Maps.

Vous pouvez créer une clé de type “Développeur” ou “Mobile”. Les deux sont gratuites et vous permettront de travailler sans problème sur votre application Windows Phone 7. Une clé “Mobile” sera nécessaire lors du déploiement d’une application utilisant le contrôle Bing Maps, en revanche, sinon vous risquez de rencontrer des problèmes dus aux limitations des autres types de clé.

Une fois que vous avez obtenu votre clé, vous allez la copier et en faire une ressource globale de votre application, car vous allez en avoir besoin à plusieurs endroits.

Ouvrez donc le fichier App.xaml, dans lequel vous allez ajouter le namespace Microsoft.Phone.Controls.Maps, comme vous l’avez fait au-dessus et vous allez ajouter votre clé à la section Resources :

<Application.Resources>
    <map:ApplicationIdCredentialsProvider x:Key="BingMapsKey" ApplicationId="[Votre clé ici]" />
</Application.Resources>

Vous pouvez maintenant la référencer depuis MainPage.xaml :

<map:Map CredentialsProvider="{StaticResource BingMapsKey}"
         ZoomBarVisibility="Visible"
         ZoomLevel="12"
         Center="48.856614,2.352222"/>

Je m’arrêterai ici pour aujourd’hui. Vous avez tout ce qu’il vous faut pour jouer un peu avec le contrôle Bing Maps. N’hésitez pas à tester différentes propriétés pour changer l’affichage.

Demain nous utiliserons les services de géolocalisation pour centrer la carte sur la position actuelle de l’utilisateur automatiquement.

Windows Phone 7 : Introduction et installation des outils

Introduction

Windows Phone 7La semaine dernière, on m’a demandé de parler au WygDay sur le développement Windows Phone 7 avec Niels. Lui, il a présenté le système à ceux qui ne le connaissaient pas et fait quelques démos sur les nouveautés que l’on peut trouver dans Mango—la nouvelle version qui sortira, a priori, au deuxième semestre. Moi, j’ai pris le pari de faire une application complète dans les 20 minutes qui restaient.

Evidemment, il s’agit d’une application plutôt simple—pas de MVVM, pas d’IoC ou d’injection de dépendances. Ce n’était pas la chasse aux mot clés à la mode, juste une application qui montre quelques concepts de base.

Etant donné qu’il y a eu un certain intérêt pour ces concepts, d’ailleurs, j’ai décidé que j’allais reprendre la démo ici en plusieurs billets courts. Voilà la “table de matières” qui reprend ma démo du WygDay :

  1. Introduction et installation des outils
  2. Création d’une application et utilisation du contrôle Bing Maps
  3. Le GPS et les services de géolocalisation
  4. Consommation d’un service OData
  5. Ajout de punaises sur une carte Bing Maps
  6. Création de nouvelles pages et navigation
  7. Création de vignettes sur la page d’accueil

Je suis sûr qu’en écrivant ces quelques articles, d’autres idées vont arriver et feront l’objet de nouveaux billets. Pour le moment, je vous invite à continuer votre lecture ci-dessous et à revenir tous les jours cette semaine pour la suite.

Installation des outils

get_the_free_toolsJ’ai promis des billets courts, donc, après une longue introduction, je vais commencer cette série par un simple lien : App Hub.

C’est sur le App Hub que Microsoft a décidé de publier, gratuitement, tout ce qu’il faut pour écrire des applications pour Windows Phone 7 (et pour XBox, mais je vais essayer de rester sur le sujet qui nous intéresse).

En cliquant sur “Download the free tools” (oui, pas de version française pour l’instant) vous avez le choix aujourd’hui entre les Windows Phone Developer Tools 7.0 qui correspondent à la version actuelle de Windows Phone 7, ou les Windows Phone Developer Tools 7.1 Beta pour la future version qu’on appelle “Mango”.

L’une comme l’autre vous permettront, a priori (sauf problèmes inattendus de la béta), d’écrire des logiciels pour la version actuelle qui pourront être publiées sur le Marketplace. Pour ma démo, on aura besoin de quelques fonctionnalités spécifiques à l’OS et/ou aux outils “Mango”, donc, si vous voulez suivre, je vous encourage à prendre la version 7.1 des outils. Vous y trouverez :

  • Microsoft Windows Phone Developer Tools 7.1 (Beta) — qui s’installeront sur une version Express de Visual Studio 2010 si vous n’avez pas ce dernier ou sur votre installation habituelle s’il est déjà sur votre machine.
  • L’émulateur Windows Phone (Beta)
  • Silverlight 4 SDK
  • Microsoft XNA Game Studio 4.0 Referesh Windows Phone Extensions
  • Microsoft Expression Blend SDK Preview pour Windows Phone 7.1
  • WCF Data Services Client pour Window Phone 7.1

Et ce sera tout pour aujourd’hui.

En attendant le billet de demain, je vous encourage à lancer Visual Studio et tester les nouveaux templates de projet qui sont apparus ; notamment ceux sous la catégorie Silverlight for Windows Phone dont le nom termine par Application. Vous pourrez les exécuter dans l’émulateur avec un simple Ctrl+F5 et commencer à vous familiariser avec.

Je veux un iPhone ! Non, je veux un AR.Drone !

Oui, je reste légèrement Apple-phobe (la marque, pas leurs produits) donc ce que je veux c’est un AR.Drone, par Parrot. Mais vu qu’il est contrôlé par iPhone ou iPod Touch, je n’ai pas trop le choix et il m’en faut un 😛

Le voici en images :

Vous aurez remarqué que la vidéo a été tournée en France (je reconnais le Parc de Bercy où j’allais courir avant) ; je me demande s’il y a moyen de rencontrer ces gens.

La sortie est prévue pour cette année, mais si vous êtes développeur de jeux vidéo on peut déjà vous en prêter un prototype (apparemment contre quelque $1000).

Je n’ai pas regardé en détail le contenu de leur SDK mais ça a l’air d’être surtout axé développement de jeux vidéo orientés realité augmentée et se basant sur des tags 2D et/ou 3D. Ce serait excellent s’ils donnaient accès directement à l’appareil, de manière à développer des contrôleurs sur d’autres plateformes comme Android ou sur PC avec une manette Xbox.

Je vous laisse regader les autres vidéos de l’AR.Drone disponibles sur le site.