[WP7] Globalisez vos applications Windows Phone 7

Le 8 août 2011 à 09:34

Afin de toucher un beaucoup plus de monde sur Windows Phone 7, traduire vos applications en plusieurs langues est un véritable plus. Un peu à la manière de WPF, il existe plusieurs méthodes pour globaliser son application (fichiers de ressources, fichiers dictionnaires XAML, frameworks… etc).

Ici on va utiliser la méthode que Microsoft recommande sur MSDN. C’est-à-dire l’utilisation des fichiers de ressources (un fichier par langue).

Tout d’abord, on va définir une langue par défaut dans notre application, en tout bon français que je suis, je vais lui dire que mon projet est français :) :

image1

Maintenant, on va lui ajouter les fichiers qui vont contenir les ressources de notre application tout d’abord pour commencer (qui seront les valeurs traduites que l’on va lui définir), ajoutez un fichier de ressource dans votre projet :

image2

Comme on a défini la langue par défaut de notre application sur « Français », le fichier Labels.resx contiendra les valeurs pour le français. Pour ajouter un fichier pour l’anglais par exemple, il faut de nouveau ajouter un fichier de ressource sur la syntaxe suivante : [Nomdufichier].[Culture].resx.

Pour la liste des cultures disponibles, allez faire un tour sur msdn.

Pour notre exemple, on va ajouter le fichier de ressource anglais :

image3

Pour valider les cultures supportées par notre application, il faut ouvrir le fichier csproj de l’application et rechercher la balise <SupportedCultures>, et lui indiquer la liste des culture que l’on supporte (à séparer par des ; entre chaque culture), ici :

<SupportedCultures>fr-FR;en-US</SupportedCultures>

On va à présent ajouter dans les fichiers de ressources les valeurs pour la traduction.
Tout simplement, on va ajouter cette valeur :

image4

Et faire de même pour le fichier anglais :

image5

On en profite pour passer le modificateur d’accès en public

Petite remarque, comme vous le pouvez le remarquer, si on ajoute une valeur dans le fichier principal « Labels.resx », rien n’est répliqué sur le fichier de ressources anglais. Alors quand on a un projet de quelques dizaines de lignes, ça peut passer encore, mais quand le fichier est trop important, ça devient vite une usine à gaz à gérer.

Pour cela, je vous conseille d’utiliser l’excellent logiciel Zeta Resource Editor. Il est gratuit, écrit en .NET et open source. Il va vous permettre de calquer facilement vos ressources sans vous prendre la tête J.

Maintenant, pour pouvoir facilement binder vos ressources à votre interface, ou à votre code, on va créer une classe statique qui va nous permettre de le faire facilement, ici je la nomme LocalizedStrings :

class LocalizedStrings
{
    private static Resources.Labels resource = new Resources.Labels();

    public Resources.Labels Localizedresources { get { return resource; } }

    public LocalizedStrings()
    {
    }
}

Ensuite, déclarer la classe dans un dictionnaire de ressource, pour qu’on puisse l’appeler directement via XAML (ici directement dans App.xaml) :

<Application.Resources>
    <WP7Lang:LocalizedStrings xmlns:WP7Lang="clr-namespace:WP7Lang"
                                        x:Key="LocalizedStrings" />
</Application.Resources>

Voilà, notre application est disponible en plusieurs langues ! Il suffit de binder les valeurs dans notre interface ou dans le code maintenant :) :


Côté XAML :

<TextBlock Name="txtHello" VerticalAlignment="Center" HorizontalAlignment="Center" 
  Text="{Binding Path=Localizedresources.Hello, Source={StaticResource LocalizedLabels}}" />

Côté code :

CultureInfo newCulture = new CultureInfo("fr-FR");

Thread.CurrentThread.CurrentCulture = newCulture;
Thread.CurrentThread.CurrentUICulture = newCulture;

 

Par contre, vous l’avez surement remarqué mais lorsque vous changez de Culture, les valeurs ne sont pas automatiquement changé dans votre UI (juste dans votre code si vous appelez les ressources vous-même).

C’est assez logique car en effet, on ne notifie pas l’interface des changements qui sont intervenus, pour cela il faut passer par INotifyPropertyChanged, donc nous allons modifier LocalizedStrings comme ceci :

public class LocalizedStrings : INotifyPropertyChanged
{
    private static readonly Resources.Labels Resource = new Resources.Labels();
    public Resources.Labels Localizedresources { get { return Resource; } }

    public LocalizedStrings()
    {
        
    }

    public void ChangeLanguage(String codeLang)
    {
        CultureInfo newCulture = new CultureInfo(codeLang);
        Resources.Labels.Culture = newCulture;

        Thread.CurrentThread.CurrentCulture = newCulture;
        Thread.CurrentThread.CurrentUICulture = newCulture;

        OnPropertyChanged("Localizedresources");
    }


    #region INotifyPropertyChanged Members

    PropertyChangedEventHandler propertyChanged;
    public virtual event PropertyChangedEventHandler PropertyChanged
    {
        add { propertyChanged += value; }
        remove { propertyChanged -= value; }
    }

    public virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.propertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion
}


Maintenant dans notre code, pour récupérer l’instance de LocalizedStrings définie dans App.xaml :

private LocalizedStrings _resources = 
        Application.Current.Resources["LocalizedLabels"] 
                                            as LocalizedStrings;

 

Pour changer de langue :

_resources.ChangeLanguage("fr-FR");

 

Pour utiliser les ressources directement dans le code :

MessageBox.Show(Labels.ResourceManager.GetString("Hello"));


Voilà maintenant, lorsqu’on change de Culture, tout est immédiatement bindé dans notre interface.

Vous pouvez télécharger la source exemple ici.

A bientôt !

SDK WP7 Mango : aucun template sous Visual Studio 2010 en français

Le 26 juin 2011 à 22:51

Sur un de mes postes de travail, j’ai Visual Studio 2010 Ultimate en français d’installé. Lorsque j’ai installé le SDK WP7 de Mango sur le PC (SDK disponible qu’en anglais donc), je me suis retrouvé avec un Visual Studio sans les templates WP7. Même si on peut ouvrir Blend créer le projet, puis revenir sur VS, ce n'est pas optimal.

image

Donc j’ai cherché sur internet s’il y avait une solution “officielle”, mais comme je n’ai rien trouvé, voici la solution que je propose ; il faut tout d’abord se rendre dans le dossier :

 

x:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\
                                              CSharp\Silverlight for Windows Phone

 

Copier ou renommer le dossier nommé “1033” en “1036” (code français, 1033 représentant l’anglais).

Puis lancer en mode administrateur la commande suivante, celle-ci permettant à Visual Studio de remettre à jour la liste des templates :

devenv.exe /InstallVSTemplates /ResetSettings

 

image

 

Et voilà, vous allez de nouveau bénéficier des templates WP7 sous Visual Studio 2010 !

image

A bientôt !

Les Afterworks des Communautés Microsoft arrivent en Lorraine !

Le 6 mai 2011 à 21:00

Evenement-Lorraine

Après Paris, Rennes, Nantes, Lille et Lyon, les Afterworks des communautés Microsoft arrivent en Lorraine (edit : et en Provence) !

Les Afterworks des Communautés Microsoft sont des évènements mensuels organisés pour les Communautés Microsoft et tous ceux qui souhaitent découvrir cet univers.

Ces évènements ont pour objet de rassembler de manière mensuelle, dans un même lieu convivial, l’ensemble des acteurs du monde communautaire Microsoft. Ces évènements sont donc ouverts à tous les MUG (Microsoft User Groups), aux clubs informatiques, aux communautés en ligne, aux MVP (Most Valuable Professional), aux MSP (Microsoft Student Partners), aux partenaires Microsoft, mais également à toute personne souhaitant échanger autour des technologies et des produits Microsoft et de leurs écosystèmes.

Durant ces soirées, une ou plusieurs thématiques pourront être abordées selon l’actualité mais ce sera essentiellement un moment privilégié pour échanger entre communautés, entre passionnés et avec les équipes Microsoft.

La première soirée qui sera organisée se passera à Nancy, le 25 mai de 20h00 à 23h00, la veille des Microsoft Days ! Elle aura lieu au Floor.

Si vous souhaitez vous joindre à nous, vous pouvez vous inscrire sur la page officiel de l’évènement sur Facebook et rejoindre notre groupe.

Venez nombreux !

A bientôt ! ;)

[WP7] Présentation et utilisation des différentes Tasks

Le 4 mai 2011 à 09:55

Pour les tâches les plus courantes, comme choisir ou prendre des photos, envoyer des e-mails ou des SMS, il existe un ensemble de tâches qui sont disponibles dans l’espace de nom Microsoft.Phone.Tasks.

Les différentes tâches sont :

CameraCaptureTask

Permet à l’application courante de lancer l’application de l’appareil photo.
Cette option permet à l’utilisateur de prendre une photo.

EmailAddressChooserTask

Permet à l’application courante de lancer l’application Contacts.
Cette option permet d’obtenir l’adresse e-mail d’un contact sélectionné par l’utilisateur.

EmailComposeTask

Permet à l’application courante de lancer la création d’un nouvel e-mail dans Outlook.
Cette option permet aux utilisateurs d’envoyer des e-mails.

MarketplaceDetailTask

Permet à l’application courante de lancer l’application Marketplace et d’afficher la page des détails d’un produit spécifié.

MarketplaceHubTask

Permet à l’application courante de lancer l’application Marketplace.

MarketplaceReviewTask

Permet à l’application courante de lancer l’application Marketplace et d’afficher la page des avis d’un produit spécifié.

MarketplaceSearchTask

Permet à l’application courante de lancer l’application Marketplace et d’afficher les résultats d’une recherche spécifiée.

MediaPlayerLauncher

Permet à l’application courante de lancer Media Player.

PhoneCallTask

Permet à l’application de lancer l’application Téléphone.
Cette option permet de téléphoner à partir de l’application courante.

PhoneNumberChooserTask

Permet à l’application courante de lancer l’application Contacts.
Cette option permet d’obtenir le numéro de téléphone d’un contact sélectionné par l’utilisateur.

PhotoChooserTask

Permet à l’application courante de lancer la sélection photo.
Cette option permet d’obtenir une photo sélectionnée par l’utilisateur.

SaveEmailAddressTask

Permet à l’application courante de lancer l’application Contacts.
Cette option permet à l’utilisateur d’enregistrer une adresse e-mail de votre application sur un nouveau ou un contact existant.

SavePhoneNumberTask

Permet à l’application courante de lancer l’application Contacts.
Cette option permet à l’utilisateur d’enregistrer un numéro de téléphone de votre application à un nouveau ou un contact existant.

SearchTask

Permet à l’application courante de lancer la recherche web.

SmsComposeTask

Lance l’application SMS pour créer un nouveau message.

WebBrowserTask

Permet à l’application courante de lancer l’application Internet Explorer.

 

Maintenant on va mettre en pratique l’utilisation des Tasks !


CameraCaptureTask, cette tâche va nous permettre de récupérer la photo que l’utilisateur vient de prendre pour notre application :

public partial class MainPage : PhoneApplicationPage
{
    private CameraCaptureTask _cameraCaptureTask;

    public MainPage()
    {
        InitializeComponent();

        _cameraCaptureTask = new CameraCaptureTask();
        _cameraCaptureTask.Completed += 
                             new EventHandler<PhotoResult>(_cameraCaptureTask_Completed);
    }

    private void btnCamera_Click(object sender, RoutedEventArgs e)
    {
        _cameraCaptureTask.Show();
    }

    void _cameraCaptureTask_Completed(object sender, PhotoResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            BitmapImage bmp = new BitmapImage();
            bmp.SetSource(e.ChosenPhoto);
            // Affichage, enregistrement... etc
        }
    }
}

 

EmailChooserAddressTask, cette tâche va nous permettre de récupérer le mail que l’utilisateur va sélectionner :

public partial class MainPage : PhoneApplicationPage
{
    private EmailAddressChooserTask _emailAddressChooserTask;

    public MainPage()
    {
        InitializeComponent();

        _emailAddressChooserTask = new EmailAddressChooserTask();
        _emailAddressChooserTask.Completed += 
                        new EventHandler<EmailResult>(emailAddressChooserTask_Completed);
    }

    private void btnEmailChooser_Click(object sender, RoutedEventArgs e)
    {
         _emailAddressChooserTask.Show();
    }

    void emailAddressChooserTask_Completed(object sender, EmailResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            MessageBox.Show(e.Email);
        }
    }
}

 

image


EmailComposeTask, pour envoyer un nouveau mail via Outlook :

private void btnEmail_Click(object sender, RoutedEventArgs e)
{
    EmailComposeTask emailComposeTask = new EmailComposeTask();

    emailComposeTask.To = "destinataire@wp7";
    emailComposeTask.Cc = "encopie@wp7";
    emailComposeTask.Subject = "Object : Test mail";
    emailComposeTask.Body = "Hello... world";

    emailComposeTask.Show();
}

 

MarketplaceDetailTask, permet d’afficher la page d’une application spécifiée par un GUID :

MarketplaceDetailTask marketDetailTask = new MarketplaceDetailTask();
marketDetailTask.ContentType = MarketplaceContentType.Applications;
marketDetailTask.ContentIdentifier = "{votre_guid}";
marketDetailTask.Show();

 

Il est bien sur possible d’afficher de la musique avec MarketplaceContentType.Music;

 

image

 

MarketplaceHubTask, lance l’application Marketplace sur le téléphone. On peut spécifie le type de contenu à afficher avec la propriété ContentType avec une valeur de l’énumération MarketplaceContentType :

MarketplaceHubTask marketplaceHubTask = new MarketplaceHubTask();
marketplaceHubTask.ContentType = MarketplaceContentType.Music;
marketplaceHubTask.Show();

 

image

 

MarketplaceReviewTask lance l’application Marketplace et affiche les avis de l’application en cours :

MarketplaceReviewTask marketplaceReviewTask = new MarketplaceReviewTask();
marketplaceReviewTask.Show();

 

MarketplaceSearchTask lance l’application Marketplace et affiche le résultat d’une recherche basée sur les mots-clefs qu’on a définis :

MarketplaceSearchTask marketplaceSearchTask = new MarketplaceSearchTask();
marketplaceSearchTask.SearchTerms = "microsoft";
marketplaceSearchTask.Show();

 

image

 

MediaPlayerLauncher nous permet de lancer une vidéo :

MediaPlayerLauncher mediaPlayerLauncher = new MediaPlayerLauncher();
// La vidéo se trouve dans le répertoire de l'application 
mediaPlayerLauncher.Location = MediaLocationType.Install; 
mediaPlayerLauncher.Media = new Uri("lavideo.wmv", UriKind.Relative);
mediaPlayerLauncher.Controls = MediaPlaybackControls.Pause | 
                               MediaPlaybackControls.Rewind | 
                               MediaPlaybackControls.Stop; // boutons dispos
mediaPlayerLauncher.Show();

 

PhoneCallTask nous permet de lancer un appel au numéro qu’on va définir dans l’application :

PhoneCallTask phoneCallTask = new PhoneCallTask();
phoneCallTask.DisplayName = "Orange pro";
phoneCallTask.PhoneNumber = "3901";
phoneCallTask.Show();

 

image

 

PhoneNumberChooserTask permet à l’utilisateur de choisir un contact et que son numéro soit envoyé vers l’application courante:

public partial class MainPage : PhoneApplicationPage
{
    private PhoneNumberChooserTask _phoneNumberChooserTask;

    public MainPage()
    {
        InitializeComponent();

        _phoneNumberChooserTask = new PhoneNumberChooserTask();
        _phoneNumberChooserTask.Completed += 
                       new EventHandler<PhoneNumberResult>(phoneNumberChooserTask_Completed);
    }

    private void btnEmailChooser_Click(object sender, RoutedEventArgs e)
    {
        _phoneNumberChooserTask.Show();
    }

    void phoneNumberChooserTask_Completed(object sender, PhoneNumberResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            MessageBox.Show(e.PhoneNumber);
        }
    }
}

 

PhotoChooserTask permet à l’utilisateur de choisir une photo et de la renvoyer à l’application courante :

public partial class MainPage : PhoneApplicationPage
{
    private PhotoChooserTask _photoChooserTask;

    public MainPage()
    {
        InitializeComponent();

        _photoChooserTask = new PhotoChooserTask();
        _photoChooserTask.Completed +=
                        new EventHandler<PhotoResult>(photoChooserTask_Completed);
    }

    private void btnPhotoChooser_Click(object sender, RoutedEventArgs e)
    {
        _photoChooserTask.Show();
    }

    void photoChooserTask_Completed(object sender, PhotoResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            System.Windows.Media.Imaging.BitmapImage bmp =
                                 new System.Windows.Media.Imaging.BitmapImage();
            bmp.SetSource(e.ChosenPhoto);

            //traitement
        }
    }
}

 

image


SaveEmailAddressTask permet de sauvegarder une adresse e-mail :

public partial class MainPage : PhoneApplicationPage
{
    private SaveEmailAddressTask _saveEmailAddressTask;

    public MainPage()
    {
        InitializeComponent();

        _saveEmailAddressTask = new SaveEmailAddressTask();
        _saveEmailAddressTask.Completed += 
                       new EventHandler<TaskEventArgs>(saveEmailAddressTask_Completed);
    }

    private void btnSaveMail_Click(object sender, RoutedEventArgs e)
    {
        _saveEmailAddressTask.Email = "mail@localhost";
        _saveEmailAddressTask.Show();
    }
   
    void saveEmailAddressTask_Completed(object sender, TaskEventArgs e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            MessageBox.Show("Enregistrement OK");
        }
        else if (e.TaskResult == TaskResult.Cancel)
        {
            MessageBox.Show("Annulé");
        }
    }
}
 

image


SavePhoneNumberTask permet de sauvegarder un numéro de téléphone :

public partial class MainPage : PhoneApplicationPage
{
    private SavePhoneNumberTask _savePhoneNumberTask;

    public MainPage()
    {
        InitializeComponent();

        _savePhoneNumberTask = new SavePhoneNumberTask();
        _savePhoneNumberTask.Completed += 
                   new EventHandler<TaskEventArgs>(savePhoneNumberTask_Completed);
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        _savePhoneNumberTask.PhoneNumber = "3901";
        _savePhoneNumberTask.Show();

    }

    void savePhoneNumberTask_Completed(object sender, TaskEventArgs e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            MessageBox.Show("Enregistrement OK");
        }
        else if (e.TaskResult == TaskResult.Cancel)
        {
            MessageBox.Show("Annulé");
        }
    }
}

 

image


SearchTask permet de faire une recherche avec la fonction recherche du téléphone :

SearchTask searchTask = new SearchTask();
searchTask.SearchQuery = "Microsoft";
searchTask.Show();

 

image


SmsComposeTask permet d’envoyer des SMS depuis l’application courante :

SmsComposeTask smsComposeTask = new SmsComposeTask();
smsComposeTask.To = "3901";
smsComposeTask.Body = "Mon SMS";
smsComposeTask.Show();

 

image


WebBrowserTask permet de lancer une page internet dans le navigateur internet du téléphone :

WebBrowserTask webBrowserTask = new WebBrowserTask();
webBrowserTask.URL = "http://www.microsoft.com";
webBrowserTask.Show();

 

image

A bientôt !

[.NET] Utilisez IIS Express à la place de ASP.NET Development Server (Cassini)

Le 15 mars 2011 à 15:11

Aujourd’hui, lorsqu’on développe un site ou une application web .NET, nous avons deux possibilités qui s’offre à nous pour le déploiement et les tests associés : soit utiliser ASP.NET Development Server intégré à Visual Studio (Cassini) ou soit déployer directement le projet sur un serveur IIS.

Bien que ASP.NET Development Server peut suffire dans bien des cas, il n’offre pas toutes les possibilités qu’offre IIS (par exemple, le support du SSL ou de l’URL Rewriting). Et l’utilisation d’un serveur IIS nous fait passer d’un extrême à l’autre et peut également poser des problèmes (soit il faut avoir un serveur dédié pour les tests, soit il faut utiliser IIS de sa machine, qui n’est peut-être pas de la même version que la version sur laquelle le serveur sera déployé).

C’est dans cette optique que Microsoft a décidé de créer une nouvelle version d’IIS orienté développeurs : IIS Express 7.5 (cette version est d’ailleurs intégré par défaut dans l’outil WebMatrix).

Cette version combine le meilleur des deux mondes et propose un serveur léger et très facile à installer (il pèse moins de 10mo et aucune administration avancée n’est à prévoir), il fonctionne également côte-à-côte d’un serveur IIS si vous l’avez d’installé sur votre machine. IIS Express supporte aussi les modules, vous pouvez très bien intégrer PHP à IIS Express (via le module FastCGI). Et pour finir, il fonctionne aussi bien sur XP que sous Windows 7 :-).

Pour télécharger IIS Express, suivez-ce lien.

L’installation est très rapide et l’intégration avec Visual Studio 2010 est parfaite (il faut tout de même le SP1 d’installé).

Pour utiliser IIS Express au lieu de ASP.NET Development Server, il suffit de cliquer droit sur le projet, et de sélectionner “Utiliser IIS Express…”

image

 

Vous pouvez bien sur revenir ensuite sur ASP.NET Development Server, en faisant la même manipulation, sauf que cette fois-ci sera disponible “Utiliser le serveur Visual Studio Development…”.

Si vous souhaitez utiliser IIS Express par défaut dans vos projets, vous avez la possibilité de le configurer dans les options de Visual Studio

image

 

Ensuite, tout se passera “comme avant”. La différence se fera dans vos projets à partir du moment où vous aurez besoin d’utiliser des fonctionnalités non disponibles dans Cassini tel que le support du protocole SSL.

image

 

image

 

Comme vous avez pu le constater l’utilisation d’IIS Express est très facile et surtout totalement intégrer à notre outil de développement préféré Visual Studio :-).

A bientôt !

A propos de l'auteur

Mathieu Perrein - Software Solutions Manager, Software Architect, Trainer MCT, MSP de 2010 à 2012.

 

MSP

 

MSP

MSP

 MSPD

MCT

 

Facebook

 

Ce blog est strictement personnel et les opinions exprimées ici n'engagent donc que moi, et pas mon employeur.

Tags

Vous avez désactivé JavaScript ou bien vous possédez une ancienne version d'Adobe Flash Player. Téléchargez la dernière version de Flash Player.