Plan du site  
pixel
pixel

Articles - Étudiants SUPINFO

Première application mobile avec Xamarin et Prism

Par Nicolas MOUGINOT Publié le 09/12/2019 à 11:18:26 Noter cet article:
(0 votes)
Avis favorable du comité de lecture

Introduction

Dans cet article, nous allons créer une application mobile cross-platform (android et iOS) grâce à Xamarin en utilisant le design pattern MVVM. Pour cela, nous utiliserons la librairie Prism ! Cet article vous expliquera comment installer visual studio, créer votre première application avec prism, utiliser les éléments xaml de base (bouton, champ de texte, affichage de texte ....), la navigation et les commandes.

Définition MVVM

MVVM (model - view - ViewModel) désigne un design pattern (Un design pattern est une façon de structurer son code qui permet de simplifier la compréhension et la maintenabilité d'un code. Il en existe plusieurs qui ont des avantages variés et qui répondent à des contraintes différentes) Un des plus connus est le MVC, qui a pour but de lier très fortement l'affichage aux données et de limiter le code qui exprime le lien entre ces deux interfaces, cela fonctionne principalement autour d'un système de binding.

Installation de visual studio et de prism

Sur la page de téléchargement de visual studio, choisissez la version Community. Une fois l'installation terminée, vous devriez avoir un écran avec des composants à choisir et à installer. Vous devez cocher "Développement mobile en .NET" puis cliquer sur Installer en bas à droite.

Lancer visual studio puis cliquer sur "Continuer sans code". Une fois l'IDE ouvert, allez sur le menu "Extensions" dans la barre du haut puis dans le sous-menu "Gérer les extensions". (Vous pouvez aussi utiliser le raccourci alt+X+G). Dans la barre de recherche en haut à droite, rechercher "Prism" puis télécharger "Prism Template Pack". Il vous faut relancer visual studio après cela.

Création de l'application prism

Lancer visual studio, cliquer sur "Créer un projet" et dans la barre de recherche, rechercher "prism". Sélectionner Prism Blank App (Xamarin.Forms) et cliquer sur suivant. Choisissez le nom et l'emplacement que vous voulez. La popup Prism project wizard devrais apparaitre, sélectionner uniquement android et iOS.

Pour compiler l'application, nous allons avoir besoin de modifier le projet de démarrage. En haut vous devriez avoir un icone "play" vert, et à sa gauche une fenêtre de sélection avec le nom de votre projet. Cette fenêtre vous permettra de modifier le projet de démarrage en .Android.

Puis il vous suffit de cliquer sur "Emulateur Android" à droite du bouton play. Une fenêtre "Android Device Manager" devrais s'ouvrir et vous proposer de créer un téléphone virtuel. Valider le tout et à la fin du téléchargement il faut démarrer l'émulateur. Un fois cela fait, vous pouvez lancer le projet avec le bouton "play" de visual studio. Votre application devrait s'ouvrir dans le téléphone virtuel.

Les bases du XAML

Le xaml est utilisé pour créer les pages de l'application. Il représente les données graphiques. En MVVM on appel cela une "View". Dans le dossier Views de votre application vous devriez trouver une page "MainPage.xaml".

Les balises les plus utilisées sont :

  • <Label /> : Balise pour afficher du texte

  • <Entry /> : Balise pour que l'utilisateur puissent écrire du texte

  • <ListView></ListView> : Balise utilisé pour afficher une quantité variable d'éléments

  • <StackLayout></StackLayout> : Balise pour organiser les autres éléments de la page xaml. Elle n'affiche rien à l'écran mais elle permet d'empiler les éléments verticalement ou horizontalement.

  • <Grid></Grid> : Balise pour structurer de façon précise les autres éléments xaml.

Au début on utilisera principalement le <StackLayout>. Voici le code xaml d'une page qui permet de saisir le nom, le prénom et l'âge d'une personne :

Code copi/collable en dessous suite à un problème de mise en page liée à XMLmind : Code Partie 5 : Les bases du XAML

Le binding

Le principe le plus important en MVVM. Le binding va vous permettre de laisser vos données se mettre à jour sans votre intervention grâce à un système d'évent. On va commencer par créer un Model (une classe représentant des données) représentant une personne. Pour cela, créer un nouveau dossier (clic droit sur votre projet principal => ajouter => Nouveau dossier) nommé Model puis ajouter une nouvelle classe dedans. (clic droit sur le dossier "Model" => Ajouter => Classe...) Nommer cette nouvelle classe "Utilisateur". Ajouter dedans 3 attributs, 2 string Nom et Prenom puis un int Age. Pensez à passer la classe en public !

public class Utilisateur { public
      string Nom { get; set; } public string Prenom { get; set; } public int
      Age { get; set; } }

Maintenant nous allons aller dans le ViewModel de notre MainPage (Dossier ViewsModels => MainPageViewModel.cs), en dessous du constructeur de la classe, ajouter une propriété comme ceci :

private Utilisateur _user = new
      Utilisateur() { Nom = "mon nom", Prenom = "mon prenom ", Age = 20 };
      public Utilisateur User { get { return _user; } set { SetProperty(ref
      _user, value); } }

Les valeurs par défaut sont maintenant affichées sur les <entry> et si l'on modifie les champs, les valeurs de l'objet Utilisateur seront également modifiées.

Bon, vu que le résultat n'est pas visible, on va faire une autre propriété plus basique avec un affichage. Ne modifiiez pas le reste du code en rapport avec la classe User, on va l'utiliser dans la partie suivante ! :)

Voilà notre nouvelle propriété :

private string _name = "Joe Hunter";
      public string Name { get { return _name; } set { SetProperty(ref _name,
      value); } }

Il ne vous reste plus qu'à ajouter dans le code XAML une <Entry> pour le modifier et un <label> pour pouvoir voir les modifications !

Ajouter une entry pour modifier la propriété nom

Ajouter un label pour afficher les modifications

Quand l'application est lancée, si vous modifiez l'Entry avec le name le label se met à jour automatiquement !

Les commandes

Les commandes permettent de faire des interactions avec l'utilisateur?. Une de leurs utilisations les plus basiquez est sur les boutons. Nous allons créer un bouton pour afficher les informations de notre User, grâce à cela on pourra voir comment il est mis à jour en fonction de nos modifications dans les Entry Nom / Prenom / Age.

Dans le MainPageViewModel il vous faut ajouter dans le constructeur :

DisplayUserCommand = new
      DelegateCommand(DisplayUser);

Puis en dessous du constructeur, il vous faut définir l'action de la commande quand elle est appelée :

#region DisplayUser Command public
      DelegateCommand DisplayUserCommand { get; set; } private async void
      DisplayUser() { Console.WriteLine($"Informations Utilisateur. Nom :
      {User.Nom}, prenom :{ User.Prenom}, Age: { User.Age}"); }
      #endregion

Maintenant il n'y a plus qu'à modifier le code XAML pour ajouter un bouton et le Bind sur la commande :

<Button Text="Afficher les informations User"
      Command="{BindingDisplayUserCommand}">

Vous avez ajouté un bouton sur l'écran qui vous permet d'afficher dans la console de visual studio le nom, le prénom, et l'âge de l'objet user ! Vous pouvez enfin essayer de modifier la valeur et vérifier que cela fonctionne bien avec le retour console :)

Navigation entre pages

La navigation est très simple car on utilise prism et c'est lui qui va nous mettre à disposition des fonctions pour la navigation.

Pour commencer, nous devons créer de nouvelles pages.

Dans le menu à droite, faite un clic droit sur le fichier Views, puis "Add" et "New Item..."

Dans la page qui apparait, allez dans "Prism" sur le menu de gauche, sélectionner "Prism NavigationPage (Xamarin.Forms)" et changer le nom en PrismNP1.

Normalement dans votre menu à droite, deux nouvelles pages ont été ajoutées, PrismNP1.xaml dans le fichier Views et PrismNP1ViewModel dans le fichier ViewModels. Il reste quelques modifications à leur apporter pour les intégrer dans le projet.

Pour la page PrismNP1ViewModel.cs, il vous faut modifier l'héritage de la classe PrismNP1ViewModel qui est normalement BindableBase en ViewModelBase. Il vous faut ensuite modifier le constructeur comme ceci :

public
      PrismNP1ViewModel(INavigationService navigationService) :
      base(navigationService) { }

Pour la page PrismNP1.xaml il faut modifier la <NavigationPage> en <ContentPage> puis ajouter le binding du titre avec la ligne Title="{Binding Title}" dans la balise <ContentPage>. Voilà le résultat après modification :

<?xml version="1.0" encoding="utf-8" ?>
      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:prism="http://prismlibrary.com"
      prism:ViewModelLocator.AutowireViewModel="True"
      x:Class="FirstAppPrism.Views.PrismNP1" Title="{Binding Title}">
      <StackLayout HorizontalOptions="CenterAndExpand"
      VerticalOptions="CenterAndExpand"> <Label Text="Texte de la
      nouvelle page." /> </StackLayout>
      </ContentPage>

Attention pour la ligne x:Class="FirstAppPrism.Views.PrismNP1" elle dépend de votre projet, donc elle peut-être différente pour vous.

Il faut aussi modifier le PrismNP1.xaml.cs, la classe hérité par défaut est NavigationPage et elle doit être modifiée en ContentPage.

Pour pouvoir utiliser la navigation de prism il vous faut enregistrer vos pages. Pour cela vous devez ajouter la ligne de code suivante dans le App.xaml.cs:

containerRegistry.RegisterForNavigation<PrismNP1,
      PrismNP1ViewModel>();

Voilà ! L'ajout de la nouvelle page est enfin fini :) Nous allons pouvoir passer à la partie navigation

Dans la xaml de la main page, on ajoute un bouton :

<Button Text="Navigation nouvelle page"
      Command="{Binding NavigationNouvellePageCommand}"/>

Dans la MainPageViewModel il faut ajouter dans le constructeur l'instanciation de la nouvelle commande

NavigationNouvellePageCommand = new
      DelegateCommand(NavigationNouvellePage);

Puis la définir en dessous comme ceci :

public DelegateCommand
      NavigationNouvellePageCommand { get; set; } private void
      NavigationNouvellePage() { _navigationService.NavigateAsync("PrismNP1");
      }

Code Copiable

Suite à des problèmes liée à XMLmind Editor, l'indentation du code n'est pas possible d'où l'existence de cette section "code". Sur visual studio vous pouvez utiliser le raccourci ctrl+K+D pour automatiquement remettre en page le code.

Code d'exemple pour la partie XAML

<StackLayout HorizontalOptions="FillAndExpand"
    VerticalOptions="CenterAndExpand" Margin="20" > <StackLayout
    Orientation="Horizontal" > <Label Text="Prenom :"
    VerticalOptions="Center" /> <Entry Text="{Binding Name}"
    VerticalOptions="Center" HorizontalOptions="FillAndExpand"/>
    </StackLayout> <StackLayout Orientation="Horizontal" >
    <Label Text="Nom :" VerticalOptions="Center" /> <Entry
    Text="{Binding User.Prenom}" VerticalOptions="Center"
    HorizontalOptions="FillAndExpand" /> </StackLayout>
    <StackLayout Orientation="Horizontal" > <Label Text="Nom :"
    VerticalOptions="Center" /> <Entry Text="{Binding User.Nom}"
    VerticalOptions="Center" HorizontalOptions="FillAndExpand" />
    </StackLayout> <StackLayout Orientation="Horizontal" >
    <Label Text="Age :" VerticalOptions="Center" /> <Entry
    Text="{Binding User.Age}" VerticalOptions="Center" Keyboard="Numeric"
    HorizontalOptions="FillAndExpand" /> </StackLayout>
    </StackLayout>

Entry pour Editer la nouvelle propriété nom

<StackLayout Orientation="Horizontal" > <Label
    Text="Prenom :" VerticalOptions="Center" /> <Entry Text="{Binding
    Name}" VerticalOptions="Center" HorizontalOptions="FillAndExpand"/>
    </StackLayout>

Label pour afficher la nouvelle propriété nom

<Label Text="{Binding Name, StringFormat='Je suis
    {0}'}" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center"
    />

Code final de la page MainPageViewModel

using FirstAppPrism.Model; using
      Prism.Commands; using Prism.Mvvm; using Prism.Navigation; using System;
      using System.Collections.Generic; using System.Linq; using System.Text;
      namespace FirstAppPrism.ViewModels { public class MainPageViewModel :
      ViewModelBase { private INavigationService _navigationService; public
      MainPageViewModel(INavigationService navigationService) :
      base(navigationService) { DisplayUserCommand = new
      DelegateCommand(DisplayUser); NavigationNouvellePageCommand = new
      DelegateCommand(NavigationNouvellePage); Title = "Main Page";
      _navigationService = navigationService; } //
      ====================================================================================================
      // Command //
      ====================================================================================================
      #region DisplayUser Command public DelegateCommand DisplayUserCommand {
      get; set; } private void DisplayUser() {
      Console.WriteLine($"Informations Utilisateur. Nom : {User.Nom}, prenom :
      {User.Prenom}, Age : {User.Age}"); } #endregion #region
      NavigationNouvellePage Command public DelegateCommand
      NavigationNouvellePageCommand { get; set; } private void
      NavigationNouvellePage() { _navigationService.NavigateAsync("PrismNP1");
      } #endregion //
      ====================================================================================================
      // Property //
      ====================================================================================================
      #region User Property private Utilisateur _user = new Utilisateur() {
      Nom = "Hunter", Prenom = "Joe", Age = 20 }; public Utilisateur User {
      get { return _user; } set { SetProperty(ref _user, value); } }
      #endregion #region Name Property private string _name = "Joe Hunter";
      public string Name { get { return _name; } set { SetProperty(ref _name,
      value); } } #endregion } }

Code final de la page MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      x:Class="FirstAppPrism.Views.MainPage" Title="{Binding Title}">
      <StackLayout HorizontalOptions="FillAndExpand"
      VerticalOptions="CenterAndExpand" Margin="20" > <StackLayout
      Orientation="Horizontal" > <Label Text="Prenom :"
      VerticalOptions="Center" /> <Entry Text="{Binding Name}"
      VerticalOptions="Center" HorizontalOptions="FillAndExpand"/>
      </StackLayout> <StackLayout Orientation="Horizontal" >
      <Label Text="Nom :" VerticalOptions="Center" /> <Entry
      Text="{Binding User.Prenom}" VerticalOptions="Center"
      HorizontalOptions="FillAndExpand" /> </StackLayout>
      <StackLayout Orientation="Horizontal" > <Label Text="Nom :"
      VerticalOptions="Center" /> <Entry Text="{Binding User.Nom}"
      VerticalOptions="Center" HorizontalOptions="FillAndExpand" />
      </StackLayout> <StackLayout Orientation="Horizontal" >
      <Label Text="Age :" VerticalOptions="Center" /> <Entry
      Text="{Binding User.Age}" VerticalOptions="Center" Keyboard="Numeric"
      HorizontalOptions="FillAndExpand" /> </StackLayout> <Label
      Text="{Binding Name, StringFormat='Je suis {0}'}"
      HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center" />
      <Button Text="Afficher les informations User" Command="{Binding
      DisplayUserCommand}" /> <Button Text="Navigation nouvelle page"
      Command="{Binding NavigationNouvellePageCommand}"/>
      </StackLayout> </ContentPage>

Code final de la page PrismNP1ViewModel

using Prism.Commands; using Prism.Mvvm; using
      Prism.Navigation; using System; using System.Collections.Generic; using
      System.Linq; namespace FirstAppPrism.ViewModels { public class
      PrismNP1ViewModel : ViewModelBase { public
      PrismNP1ViewModel(INavigationService navigationService) :
      base(navigationService) { Title = "New Page 1"; } } }

Code final de la page PrismNP1.xaml

<?xml version="1.0" encoding="utf-8" ?>
      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:prism="http://prismlibrary.com"
      prism:ViewModelLocator.AutowireViewModel="True"
      x:Class="FirstAppPrism.Views.PrismNP1" Title="{Binding Title}">
      <StackLayout HorizontalOptions="CenterAndExpand"
      VerticalOptions="CenterAndExpand"> <Label Text="Texte de la
      nouvelle page." /> </StackLayout>
      </ContentPage>

Code final de la page PrismNP1.xaml

<?xml version="1.0" encoding="utf-8" ?>
      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:prism="http://prismlibrary.com"
      prism:ViewModelLocator.AutowireViewModel="True"
      x:Class="FirstAppPrism.Views.PrismNP1" Title="{Binding Title}">
      <StackLayout HorizontalOptions="CenterAndExpand"
      VerticalOptions="CenterAndExpand"> <Label Text="Texte de la
      nouvelle page." /> </StackLayout>
      </ContentPage>

Code final de la page App.xaml.cs

using Prism; using Prism.Ioc; using
      FirstAppPrism.ViewModels; using FirstAppPrism.Views; using
      Xamarin.Forms; using Xamarin.Forms.Xaml; [assembly:
      XamlCompilation(XamlCompilationOptions.Compile)] namespace FirstAppPrism
      { public partial class App { /* * The Xamarin Forms XAML Previewer in
      Visual Studio uses System.Activator.CreateInstance. * This imposes a
      limitation in which the App class must have a default constructor. *
      App(IPlatformInitializer initializer = null) cannot be handled by the
      Activator. */ public App() : this(null) { } public
      App(IPlatformInitializer initializer) : base(initializer) { } protected
      override async void OnInitialized() { InitializeComponent(); await
      NavigationService.NavigateAsync("NavigationPage/MainPage"); } protected
      override void RegisterTypes(IContainerRegistry containerRegistry) {
      containerRegistry.RegisterForNavigation<NavigationPage>();
      containerRegistry.RegisterForNavigation<MainPage,
      MainPageViewModel>();
      containerRegistry.RegisterForNavigation<PrismNP1,
      PrismNP1ViewModel>(); } } }

A propos de SUPINFO | Contacts & adresses | Enseigner à SUPINFO | Presse | Conditions d'utilisation & Copyright | Respect de la vie privée | Investir
Logo de la société Cisco, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société IBM, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sun-Oracle, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Apple, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sybase, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Novell, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Intel, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Accenture, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société SAP, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Prometric, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Toeic, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo du IT Academy Program par Microsoft, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management

SUPINFO International University
Ecole d'Informatique - IT School
École Supérieure d'Informatique de Paris, leader en France
La Grande Ecole de l'informatique, du numérique et du management
Fondée en 1965, reconnue par l'État. Titre Bac+5 certifié au niveau I.
SUPINFO International University is globally operated by EDUCINVEST Belgium - Avenue Louise, 534 - 1050 Brussels