Browsed by
Month: June 2011

Systray et mango

Systray et mango

On parle beaucoup des nouvelles fonctionnalités de mango comme : le multi-thread, les live agents ou encore les multi live-tile. Mais mango apporte aussi de nouveaux contrôles (comme le RichTextBlock, cher à David Poulin ou encore l’accès à la systray).

Concentrons nous sur les nouvelles propriétés de la systray.

Le passé

Sous Windows Phone 7.0 (cela me fait toujours aussi bizarre à écrire), nous n’avions accès qu’à la méthode “IsVisible” qui permettant comme son nom l’indique d’afficher ou non la barre  systray. Celle ci n’était pas personnalisable, si votre application possédait un fond foncé, mais que l’utilisateur avait choisi le thème clair, la barre restait blanche et ne s’intégrait pas bien dans votre design.

Pour contrer cela, les développeurs avaient donc tendance à ne pas l’afficher, ce qui altère grandement l’expérience utilisateur car il est impossible de voir l’heure ou encore de connaitre l’état du réseau (un débat que l’on a eu avec Alex Danvy).

Une solution possible sous nodo est le behavior que j’avais mis à disposition y’a quelques semaines qui cache automatiquement la systray mais qui laisse la possibilité de voir les informations en appuyant sur la partie supérieur de l’écran)

 

systray blanche lorsque le thème du téléphone est 'clair'

La personnalisation

une application française !

Mango apporte la personnalisation de la systray, que ce soit la couleur de fond ou la couleur des icônes. Pour cela deux propriétés sont disponibles :

 

  • BackgroundColor : la couleur de fond
  • ForegroundColor : la couleur des icônes

Un exemple :

<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
x:Class="WindowsPhoneApplication4.MainPage"
shell:SystemTray.IsVisible="True"
shell:SystemTray.BackgroundColor="Blue"
shell:SystemTray.ForegroundColor="Red"	>

A noter que sous blend, vous ne verrez pas de changement de couleurs, ce changement ne sera visible que dans l’émulateur ou sur un téléphone mango.

opacité à 50%

Il est aussi possible de jouer avec l’opacité de la systray grâce à la propriété Opacity. A savoir, l’opacité n’a une incidence que sur le fond pas sur les icônes, celle ci restant visibles quelque soit l’opacité choisie. Si vous affectez à backgroundColor une couleur avec transparence (#30FFFFFF par exemple), le système va ignorer le canal alpha et ne prendre en compte que les composantes RGB (comme pour l’applicationBar).

Grâce à ces trois propriétés, il est donc possible de façon assez simple de “fondre” la systray dans votre UI, le développeur n’aura donc plus aucune raison de la masquer.

Attention, tout comme l’applicationBar, changer l’opacité de la systray agrandit la zone correspondant à la page, celle-ci commençant au bord de l’écran et non plus en dessous de la systray, on gagne ainsi 32 pixels en vue portrait et 72 pixels en vue paysage.

Encore une fois, Blend ne prend pas en compte ces paramètres, il faudra donc penser l’UI avec ces quelques pixels en plus, Blend continuera à considérer le début de la page dessous la systray et non au bord de l’écran dans l’éditeur.

Enfin, il est à noter que dans l’émulateur de la version beta de mango si on ne change pas explicitement la couleur de la systray, elle reste noir quelque soit le thème choisi (sombre ou clair) contrairement à 7.0 surement un dommage collatéral de la personnalisation des couleurs.

La progression

Je me rappelle que la toute première discussion que j’ai eu avec Pierre Cauchois, notre évangéliste national Windows Phone, était sur la possibilité d’avoir accès à la ProgressBar du système afin de ne pas être obligé d’ajouter manuellement une progressBar dans notre page (avec l’effet de bord que la progressBar sera sous la systray et non au dessus). Evidemment, la réponse est arrivée quelques mois plus tard avec la sortie du SDK final : réponse négative.

Toutefois, l’équipe de développement semble avoir écouté les développeurs et a intégré cette fonctionnalité dans mango (“Windows Phone 7, c’était mon idée”)

Nous avons donc accès à la propriété ProgressIndicator pour cela, représentant un objet de type ProgressIndicator, ce dernier disposant des propriétés suivantes :

  • IsIndeterminate : état de la progressBar, semblable à la propriété éponyme du contrôle ProgressBar
  • Value : représente la valeur de la progressBar sur une échelle de 1
  • IsVisible : permet d’afficher la progressBar, vaut False par défaut

ainsi qu’une propriété spéciale :

  • Text : le texte correspondant à la progression

Celle-ci va permettre d’afficher un texte en lieu et place des icônes du téléphone, un slide vers le bas, permettra toujours d’afficher les icônes pendant quelques secondes. On peut donc utiliser cette propriété pour afficher un texte comme “téléchargement en cours”, “Fichier 4/23”, etc…

Voici un exemple d’utilisation en XAML :

 

<phone:PhoneApplicationPage
...
shell:SystemTray.IsVisible="True">
<shell:SystemTray.ProgressIndicator >
<shell:ProgressIndicator  IsVisible="True" Value="0.4" Text="Téléchargement en cours..."/>
</shell:SystemTray.ProgressIndicator>

en C# :

var progress = new Microsoft.Phone.Shell.ProgressIndicator();
progress.IsVisible = true;
progress.Value = 0.5;
Microsoft.Phone.Shell.SystemTray.SetProgressIndicator(this, progress);

Bindable ?

Vous avez sûrement déjà essayé de binder une propriété de l’objet ApplicationBar et vous avez sûrement découvert quelques secondes plus tard que cela n’était pas possible. Qu’en est il de l’objet systray ?

Pour avoir la réponse, il suffit de regarder la définition de l’objet Systray et de ProgressIndicator :


class SystemTray : DependencyObject
{
public static readonly DependencyProperty BackgroundColorProperty;
}

class ProgressIndicator : DependencyObject
{
...
}

Les deux classes sont donc des dependencyObject contenant des dependency properties, il n’y a donc aucun problème à binder leurs propriétés, on peut donc écrire sans soucis :

<shell:SystemTray.ProgressIndicator >
<shell:ProgressIndicator  IsVisible="True"  IsIndeterminate={Binding IsLoading}/>
</shell:SystemTray.ProgressIndicator>

Espérons que l’ApplicationBar aura le droit à ce même privilège dans la version finale.

désolé Julien 😉

 

Mango : attention au WebClient !!!

Mango : attention au WebClient !!!

Mango apporte pleins de nouvelles fonctionnalité et promet une retro compatibilité avec les anciennes applications sous “Nodo” and Co.

Dans les faits c’est le cas, enfin presque…

Le problème

Vous savez déjà que je ne suis pas fan de WebClient, je préfère l’utilisation des WebRequests car on est des hommes, des vrais… non sérieux, car il permet plus de contrôles.

Revenons au fait : WebClient va poser des problèmes dans l’état quand vous ferez la mise à jour Mango, car en effet, il va être légèrement modifié pour moins occuper le thread UI (et donc avec une plus grande fluidité dans son IHM).

Auparavant, lorsque l’on utilisait un WebClient, les callbacks étaient toujours appelées dans le thread UI, quelque soit le thread d’appel original. Avec mango, si le WebClient les callbacks sont appelés dans des threads semblables au thread appelant. Donc si WebClient est appelé dans un thread différent de UI, la réponse ne sera pas dans le thread UI, donc si je manipule des contrôles utilisateurs ou des propriétés qui sont bindées à des contrôles utilisateurs, une exception de type UnauthorizedAccessException “Invalid cross-thread access.” va être lancée.

Solution

Avant tout, précisons que le SDK est en version beta, il est possible que les webclient évoluent ou soit doublé (WebClientEx ?). Voir même : le téléphone reconnaitra que l’application est pré-mango et donc utilisera l’ancienne implémentation de WebClient.

Toutefois, pour éviter ce problème, il faut utiliser un dispatcher autour des instructions intéragissant avec l’UI dans les callbacks des webclients lancés dans les thread non UI :

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (senderb, eb) =>{
WebClient wc = new WebClient();
wc.DownloadStringCompleted += (senderr, er) =>
{
//actions n'utilisant pas l'ui ou des propriétés bindés
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//actions utilisant l'ui ou des propriétés bindés
}, null);
};
wc.DownloadStringAsync(new Uri("http://create.msdn.com", UriKind.Absolute));};
bw.RunWorkerAsync();

Si le SDK reste ainsi, pensez dès maintenant à ajouter ces instructions de dispatcher si vous ne voulez pas rencontrer de problèmes avec mango