• Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 29/04/2014

L’application Bar

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Nous ne l’avons pas encore vue, mais vous la connaissez sûrement si vous possédez un téléphone équipé de Windows Phone. La barre d’application, si elle est présente, est située en bas de l’écran et possède des boutons que nous pouvons cliquer. Elle fait office plus ou moins de menu, accessible tout le temps, un peu comme le menu en haut des fenêtres qui existaient sur nos vieilles applications Windows.

Elle peut s'avérer très pratique et est plutôt simple d'accès, deux bonnes raisons pour pousser un peu plus loin sa découverte.

Présentation et utilisation

Si vous utilisez le SDK pour Windows Phone 7, vous l’avez sûrement déjà vue dans le code XAML sans vraiment y faire attention. Il y a un exemple d’utilisation commenté dans chaque nouvelle page créée :

<!--Exemple de code illustrant l'utilisation d'ApplicationBar-->
<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Bouton 1"/>
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Bouton 2"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 1"/>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 2"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Si vous dé-commentez ces lignes ou que vous les recopiez dans votre page Windows Phone 8, que vous démarrez l’émulateur, vous aurez la figure suivante.

Affichage de la barre d'application
Affichage de la barre d'application

La barre d’application est bien sûr ce que j’ai encadré en rouge.
Ce XAML doit être au même niveau que la page, c’est-à-dire hors du conteneur racine :

<phone:PhoneApplicationPage
    x:Class="DemoBarreApplication.MainPage"
    …>

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

    <phone:PhoneApplicationPage.ApplicationBar>
        …
    </phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>

Le XAML est plutôt facile à comprendre. On constate que la barre est visible, que le menu est activé et qu’elle possède deux boutons, « bouton 1 » et « bouton 2 », ainsi que deux éléments de menu, « ÉlémentMenu 1 » et « ÉlémentMenu 2 ».
Pour afficher les éléments de menu, il faut cliquer sur les trois petits points en bas à droite. Cela permet également de voir le texte associé à un bouton, comme vous pouvez le voir sur la figure suivante.

Les éléments de menu de la barre
Les éléments de menu de la barre

Par contre, nos images ne sont pas très jolies. En effet, le code XAML fait référence à des images qui n’existent pas dans notre solution. La croix affichée représente donc l’absence d’image.
Ces images sont des icônes. Elles sont toujours visibles sur la barre d’application alors que ce n’est pas forcément le cas des éléments de menu. Il est donc primordial que ces icônes soient les plus représentatives possibles, car pour voir la légende de l’icône, il faut cliquer sur les trois petits points permettant d’afficher la suite de la barre. Les icônes doivent avoir la taille de 48x48, sachant que le cercle est ajouté automatiquement en surimpression par Windows Phone. Cela implique que la zone visible de votre icône doit être de 26x26 au centre de l’icône. Enfin, l’icône doit être de couleur blanche, sur fond transparent.
C’est un look très Modern UI que nous impose Microsoft afin de privilégier la sémantique du dessin plutôt que sa beauté. Pour nous aider, Microsoft propose un pack d’icône « Modern UI » que nous pouvons librement utiliser dans nos applications. Ce pack a été installé avec le SDK de Windows Phone, vous pouvez le retrouver à cet emplacement : C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons.

Maintenant, ajoutons deux images à notre application, disons delete.png et edit.png. Pour ce faire, créez par exemple un répertoire Icones sous le répertoire Assets et ajoutez les icônes dedans en ajoutant un élément existant. Ensuite, dans la fenêtre de propriétés, modifiez l’action de génération en « Contenu » ainsi que la copie dans le répertoire de sortie en « copier si plus récent ».
Modifiez ensuite le XAML pour utiliser nos nouvelles icônes :

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Assets/Icones/delete.png" Text="Supprimer"/>
        <shell:ApplicationBarIconButton IconUri="/Assets/Icones/edit.png" Text="Modifier"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 1"/>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 2"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Et voilà à la figure suivante le beau résultat !

Utilisation des icônes de la barre d'application
Utilisation des icônes de la barre d'application

La barre d’application est positionnée en bas de l’écran, juste au-dessus des trois boutons physiques. On ne peut pas la changer de place, mais elle sait cependant s’orienter différemment suivant l’orientation du téléphone. Par exemple, en mode paysage, nous pouvons voir la rotation des images et du texte :

La barre d'application subit une rotation lors du changement d'orientation du téléphone
La barre d'application subit une rotation lors du changement d'orientation du téléphone

Il faudra bien sûr au préalable faire en sorte que la page supporte les deux orientations comme nous l’avons vu dans un chapitre précédent.

Bon, une barre avec des boutons c’est bien, mais si on pouvait cliquer dessus pour faire des choses, ça serait pas plus mal non ?
Rien de plus simple, vous pouvez ajouter l’événement de clic sur un bouton ou sur un élément de menu :

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Assets/Icones/delete.png" Text="Supprimer" Click="ApplicationBarIconButton_Click_1"/>
        <shell:ApplicationBarIconButton IconUri="/Assets/Icones/edit.png" Text="Modifier"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 1" Click="ApplicationBarMenuItem_Click_1"/>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 2"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Avec :

private void ApplicationBarIconButton_Click_1(object sender, EventArgs e)
{
    MessageBox.Show("Voulez-vous vraiment supprimer ?", "Suppression", MessageBoxButton.OKCancel);
}

private void ApplicationBarMenuItem_Click_1(object sender, EventArgs e)
{
    MessageBox.Show("Menu !");
}

Observez la figure suivante pour le rendu.

Le clic sur un bouton de menu déclenche l'affichage du message
Le clic sur un bouton de menu déclenche l'affichage du message

On peut jouer sur les propriétés de la barre d’application. Citons par exemple sa propriété IsVisible qui permet de la rendre visible ou invisible. Citons encore la propriété Opacity qui permet d’afficher des contrôles sous la barre d’application, par exemple avec le XAML suivant :

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

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock Text="MON APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
        <TextBlock Text="nom de la page" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <Canvas>
            <TextBlock Text="Je suis caché" Foreground="Red" FontSize="50" Canvas.Top="500" />
        </Canvas>
    </Grid>
</Grid>

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Assets/Icones/delete.png" Text="Supprimer" Click="ApplicationBarIconButton_Click_1"/>
        <shell:ApplicationBarIconButton IconUri="/Assets/Icones/edit.png" Text="Modifier"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 1" Click="ApplicationBarMenuItem_Click_1"/>
            <shell:ApplicationBarMenuItem Text="ÉlémentMenu 2"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Si vous démarrez l’application, le texte rouge est invisible car il est derrière la barre d’application. Si vous changez l’opacité en mettant par exemple 0.5 :

<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" Opacity="0.5">

le texte apparaîtra sous la barre d’application (voir la figure suivante).

Utilisation de l'opacité sur la barre d'application
Utilisation de l'opacité sur la barre d'application

Pour les boutons, on peut remarquer en plus la propriété IsEnabled qui permet de désactiver ou d’activer un bouton.
Il est bien sûr possible de manipuler la barre d’application par le code-behind, via la propriété ApplicationBar. Par exemple, je peux rendre invisible la barre d’application de cette façon :

ApplicationBar.IsVisible = false;

Ou modifier le texte du premier bouton :

((ApplicationBarIconButton)ApplicationBar.Buttons[0]).Text = "Changement dynamqiue";

Pour les éléments de menu, le principe est le même que pour les boutons.

Notons juste qu’il est possible de s’abonner à un événement qui permet de savoir si l’état de la barre change, c’est-à-dire quand les éléments de menu sont affichés ou non. Cela permet par exemple de faire en sorte que certaines infos soient affichées différemment si jamais le menu les cache. Il s’agit de l’événement StateChanged :

private void ApplicationBar_StateChanged(object sender, ApplicationBarStateChangedEventArgs e)
{
    if (e.IsMenuVisible)
    {
        // ...
    }
}

Enfin, remarquons une dernière petite chose qui peut-être vous a intrigué. Il s’agit de l’endroit dans le XAML où est définie la barre d’application :

<phone:PhoneApplicationPage 
    …>

    <Grid x:Name="LayoutRoot" Background="Transparent">
        …
    </Grid>
 
    <phone:PhoneApplicationPage.ApplicationBar>
        …
    </phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>

J’en ai parlé un peu en haut mais vous avez vu ? Elle est au même niveau que la grille ! Alors que nous avons dit qu’un seul conteneur racine était autorisé.
C’est parce que l’objet ApplicationBar ne dérive pas de FrameworkElement, pour notre plus grand malheur d’ailleurs. La propriété ApplicationBar de la PhoneApplicationPage est une propriété de dépendance : http://msdn.microsoft.com/fr-fr/librar [...] erty(v=vs.92). C’est pour cela que nous pouvons (et d’ailleurs devons !) la mettre au niveau de la page.

Appliquer le Databinding

Étant donné que notre barre d’application n’est pas un FrameworkElement, elle ne sait pas gérer la liaison de données. Il n’est donc pas possible d’utiliser les extensions de balisage {Binding} ni les commandes sur cet élément. Ce qui pose un problème lorsque l’on fait du MVVM ou même quand il s’agit de traduire notre application.
Il y a cependant une petite astuce pour rendre notre barre application fonctionnelle avec la liaison de données ainsi qu’avec le système de commandes. Il suffit de développer une nouvelle classe qui encapsule les fonctionnalités de la classe ApplicationBar. On appelle communément ce genre de classe un wrapper.

Nous n’allons pas faire cet exercice ici vu que d’autres personnes l’ont déjà fait pour nous. C’est le cas par exemple de la bibliothèque BindableApplicationBar que nous pouvons trouver à cet emplacement : http://bindableapplicationb.codeplex.com/. Vous pouvez télécharger cette bibliothèque ou tout simplement utiliser NuGet (voir la figure suivante).

Utilisation de NuGet pour télécharger la barre d'application bindable
Utilisation de NuGet pour télécharger la barre d'application bindable

Il ne reste plus qu’à importer l’espace de nom suivant :

xmlns:barre="clr-namespace:BindableApplicationBar;assembly=BindableApplicationBar"

et à modifier notre barre comme suit :

<barre:Bindable.ApplicationBar>
    <barre:BindableApplicationBar IsVisible="{Binding EstBarreVisible}">
        <barre:BindableApplicationBarButton Command="{Binding SupprimerCommand}" Text="{Binding SupprimerText}" IconUri="/Assets/Icones/delete.png" /> 
        <barre:BindableApplicationBar.MenuItems>
            <barre:BindableApplicationBarMenuItem Text="{Binding ElementText}" Command="{Binding ElementCommand}" />
        </barre:BindableApplicationBar.MenuItems>
    </barre:BindableApplicationBar>
</barre:Bindable.ApplicationBar>

Notons la liaison de données sur la propriété IsVisible de la barre d’application, de la propriété Text du bouton ainsi que l’utilisation d’une commande lors du clic sur le bouton. Nous aurons donc un contexte qui pourra être :

public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string nomPropriete)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
    }

    private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
    {
        if (object.Equals(variable, valeur)) return false;

        variable = valeur;
        NotifyPropertyChanged(nomPropriete);
        return true;
    }

    private bool estBarreVisible;
    public bool EstBarreVisible
    {
        get { return estBarreVisible; }
        set { NotifyPropertyChanged(ref estBarreVisible, value); }
    }

    public string SupprimerText
    {
        get { return "Supprimer"; }
    }

    public string ElementText
    {
        get { return "Elément"; }
    }

    public ICommand SupprimerCommand { get; set; }
    public ICommand ElementCommand { get; set; }

    public MainPage()
    {
        InitializeComponent();
        SupprimerCommand = new RelayCommand(OnSupprimer);
        ElementCommand = new RelayCommand(OnElement);
        EstBarreVisible = true;

        DataContext = this;
    }

    private void OnSupprimer()
    {
        MessageBox.Show("Voulez-vous vraiment supprimer ?", "Suppression", MessageBoxButton.OKCancel);
    }

    private void OnElement()
    {
        EstBarreVisible = false;
    }
}

Notez que vous aurez besoin d’une classe RelayCommand, venant de votre framework MVVM préféré ou bien l’exemple simple que nous avons créé précédemment.
Grâce à cette classe, nous pouvons désormais respecter correctement le pattern MVVM, chose qui était plus difficile sans.

Mode plein écran

Vous avez dû remarquer qu’il y a tout en haut de l’écran, un petit bout qui est réservé à l’affichage de la batterie, de la qualité de la connexion, etc. Il s’agit de la barre système. Ce n’est pas vraiment la barre d’application, mais je trouve qu’il est pertinent d’en parler ici.
Il n’est pas possible de modifier le contenu de la barre système, mais il est par contre possible de la masquer afin d’avoir un mode « plein écran », grâce à une propriété.
Cette propriété est positionnée à vrai par défaut lorsque l’on crée un nouvelle page XAML, elle rend la barre système visible :

<phone:PhoneApplicationPage 
    …
    shell:SystemTray.IsVisible="True"

Nous pouvons modifier ici sa valeur en mettant False. Ou bien par code, en utilisant la classe statique SystemTray :

SystemTray.IsVisible = false;

Cela permet de récupérer 16 pixels en hauteur.
Vous aurez besoin d’inclure l’espace de nom suivant :

using Microsoft.Phone.Shell;
  • La barre d’application est un contrôle utile lorsqu’il y a besoin de faire des actions récurrentes dans une application.

  • Elle fonctionne un peu comme un menu, accessible de partout.

  • Ne supportant pas la liaison de données par défaut, il est possible d’utiliser des wrappers pour la rendre fonctionnelle avec le binding.

  • Il est recommandé de ne pas masquer la barre système, mais c’est cependant possible pour passer en mode plein écran.

Exemple de certificat de réussite
Exemple de certificat de réussite