Xamarin.Forms Navigation de l’interpréteur de commande

Télécharger l’exemple Télécharger l’exemple

Xamarin.Forms Shell inclut une expérience de navigation basée sur un URI qui utilise des itinéraires pour accéder à n’importe quelle page de l’application, sans avoir à suivre une hiérarchie de navigation définie. De plus, l’utilisateur peut revenir en arrière sans avoir à visiter toutes les pages de la pile de navigation.

La Shell classe définit les propriétés de navigation suivantes :

Les propriétés BackButtonBehavior, CurrentItem et CurrentState sont soutenus par des objets BindableProperty, ce qui signifie que ces propriétés peuvent être des cibles de liaisons de données.

La navigation est effectuée en appelant la méthode GoToAsync à partir de la classe Shell. Lorsque la navigation est sur le point d’être effectuée, l’événement Navigating est déclenché et l’événement est déclenché à la fin de la Navigated navigation.

Notes

La navigation peut toujours être effectuée entre les pages d’une application Shell à l’aide de la propriété Navigation . Pour plus d’informations, consultez Navigation hiérarchique.

Itinéraires

La navigation est effectuée dans une application Shell en spécifiant un URI vers lequel naviguer. Les URI de navigation peuvent avoir trois composants :

  • Un itinéraire, qui définit le chemin d’accès au contenu existant dans le cadre de la hiérarchie visuelle Shell.
  • Une page. Les pages qui n’existent pas dans la hiérarchie visuelle Shell peuvent être transmises en mode push à la pile de navigation depuis n’importe où dans une application Shell. Par exemple, une page de détails n’est pas définie dans la hiérarchie visuelle Shell, mais peut être envoyée (par push) sur la pile de navigation, si nécessaire.
  • Un ou plusieurs paramètres de requête. Les paramètres de requête sont des paramètres qui peuvent être transmis à la page de destination lors de la navigation.

Lorsqu’un URI de navigation comprend les trois composants, la structure est : //route/page?queryParameters

Inscrire des itinéraires

Les itinéraires peuvent être définis sur FlyoutItemles objets , TabBar, Tabet ShellContent par le biais de leurs Route propriétés :

<Shell ...>
    <FlyoutItem ...
                Route="animals">
        <Tab ...
             Route="domestic">
            <ShellContent ...
                          Route="cats" />
            <ShellContent ...
                          Route="dogs" />
        </Tab>
        <ShellContent ...
                      Route="monkeys" />
        <ShellContent ...
                      Route="elephants" />  
        <ShellContent ...
                      Route="bears" />
    </FlyoutItem>
    <ShellContent ...
                  Route="about" />                  
    ...
</Shell>

Notes

Tous les éléments dans la hiérarchie Shell sont associés à un itinéraire. Si vous ne définissez pas d’itinéraire, un itinéraire est généré au moment de l’exécution. Toutefois, la cohérence des itinéraires n’est pas garantie entre les sessions d’application.

L’exemple ci-dessus crée la hiérarchie d’itinéraires suivante, qui peut être utilisée dans la navigation par programmation :

animals
  domestic
    cats
    dogs
  monkeys
  elephants
  bears
about

Afin d’accéder à l’objet ShellContent pour l’itinéraire dogs, l’URI de l’itinéraire absolu est //animals/domestic/dogs. De même, afin d’accéder à l’objet ShellContent pour l’itinéraire about, l’URI de l’itinéraire absolu est //about.

Avertissement

Une exception ArgumentException sera levée au démarrage de l’application si un itinéraire en double est détecté. Cette exception est également levée si au moins deux routes au même niveau dans la hiérarchie partagent un nom de route.

Enregistrer les itinéraires de la page de détails

Dans le constructeur de sous-classe Shell ou tout autre emplacement qui s’exécute avant l’appel d’une route, des routes supplémentaires peuvent être inscrites explicitement pour toutes les pages de détails qui ne sont pas représentées dans la hiérarchie visuelle Shell. Cette opération est effectuée avec la méthode Routing.RegisterRoute :

Routing.RegisterRoute("monkeydetails", typeof(MonkeyDetailPage));
Routing.RegisterRoute("beardetails", typeof(BearDetailPage));
Routing.RegisterRoute("catdetails", typeof(CatDetailPage));
Routing.RegisterRoute("dogdetails", typeof(DogDetailPage));
Routing.RegisterRoute("elephantdetails", typeof(ElephantDetailPage));

Cet exemple enregistre des pages de détails, qui ne sont pas définies dans la Shell sous-classe, en tant qu’itinéraires. Vous pouvez ensuite accéder à ces pages de détails à l’aide de la navigation basée sur l’URI, n’importe où dans l’application. Les itinéraires pour ces pages sont appelés itinéraires globaux.

Avertissement

Une ArgumentException est levée si la méthode Routing.RegisterRoute tente d’enregistrer la même route dans au moins deux types différents.

Les pages peuvent également être inscrites sur des hiérarchies d’itinéraires différentes, si nécessaire :

Routing.RegisterRoute("monkeys/details", typeof(MonkeyDetailPage));
Routing.RegisterRoute("bears/details", typeof(BearDetailPage));
Routing.RegisterRoute("cats/details", typeof(CatDetailPage));
Routing.RegisterRoute("dogs/details", typeof(DogDetailPage));
Routing.RegisterRoute("elephants/details", typeof(ElephantDetailPage));

Cet exemple active la navigation contextuelle dans les pages, dans laquelle l’accès à l’itinéraire details depuis la page pour l’itinéraire monkeys affiche l’élément MonkeyDetailPage. De même, l’accès à l’itinéraire details depuis la page pour l’itinéraire elephants affiche l’élément ElephantDetailPage. Pour plus d’informations, consultez Navigation contextuelle.

Notes

Les pages dont les itinéraires ont été inscrits avec la méthode Routing.RegisterRoute peuvent être désinscrites avec la méthode Routing.UnRegisterRoute, si nécessaire.

Effectuer la navigation

Pour effectuer la navigation, vous devez d’abord obtenir une référence à la sous-classe Shell. Cette référence peut être obtenue en associant la propriété App.Current.MainPage à un objet Shell, ou via la propriété Shell.Current. La navigation peut ensuite être effectuée en appelant la méthode GoToAsync sur l’objet Shell. Cette méthode permet d’accéder à un élément ShellNavigationState puis retourne un élément Task qui se termine à la fin de l’animation de navigation. L’objet ShellNavigationState est construit par la méthode GoToAsync, à partir d’un élément string ou Uri, et sa propriété Location est définie sur l’argument string ou Uri.

Important

Lorsque vous accédez à un itinéraire depuis la hiérarchie visuelle Shell, aucune pile de navigation n’est créée. Cependant, lorsque vous accédez à une page qui ne figure pas dans la hiérarchie visuelle Shell, une pile de navigation est créée.

L’état de navigation actuel de l’objet Shell peut être récupéré via la Shell.Current.CurrentState propriété , qui inclut l’URI de l’itinéraire affiché dans la Location propriété .

Itinéraires absolus

La navigation peut être effectuée en spécifiant un URI absolu valide en tant qu’argument pour la méthode GoToAsync :

await Shell.Current.GoToAsync("//animals/monkeys");

Cet exemple accède à la page pour l’itinéraire monkeys, avec l’itinéraire défini sur un objet ShellContent. L’objet ShellContent qui représente l’itinéraire monkeys est un enfant d’un objet FlyoutItem, dont l’itinéraire est animals.

Itinéraires relatifs

La navigation peut également être effectuée en spécifiant un URI relatif valide en tant qu’argument pour la méthode GoToAsync. Le système d’acheminement tente de faire correspondre l’URI à un objet ShellContent. Par conséquent, si tous les itinéraires d’une application sont uniques, la navigation peut être effectuée en spécifiant uniquement le nom d’itinéraire unique en tant qu’URI relatif.

Les formats d’itinéraire relatifs suivants sont pris en charge :

Format Description
route La hiérarchie d’itinéraire sera recherchée pour l’itinéraire spécifié, vers le haut à partir de la position actuelle. La page correspondante est envoyée à la pile de navigation.
/route La hiérarchie de routage sera recherchée à partir de l’itinéraire spécifié, vers le bas à partir de la position actuelle. La page correspondante est envoyée à la pile de navigation.
//route La hiérarchie d’itinéraire sera recherchée pour l’itinéraire spécifié, vers le haut à partir de la position actuelle. La page correspondante remplace la pile de navigation.
///route La hiérarchie de routage est recherchée pour l’itinéraire spécifié, vers le bas à partir de la position actuelle. La page correspondante remplace la pile de navigation.

L’exemple suivant accède à la page de l’itinéraire monkeydetails :

await Shell.Current.GoToAsync("monkeydetails");

Dans cet exemple, l’itinéraire monkeyDetails est recherché dans la hiérarchie jusqu’à ce que la page correspondante soit trouvée. Lorsque la page est trouvée, elle est envoyée à la pile de navigation.

Navigation contextuelle

Les itinéraires relatifs permettent une navigation contextuelle. Par exemple, considérez la hiérarchie d’acheminement suivante :

monkeys
  details
bears
  details

Lorsque la page inscrite pour l’itinéraire monkeys s’affiche, l’accès à l’itinéraire details affichera la page inscrite pour l’itinéraire monkeys/details. De même, lorsque la page inscrite pour l’itinéraire bears s’affiche, l’accès à l’itinéraire details affichera la page inscrite pour l’itinéraire bears/details. Pour plus d’informations sur la façon d’inscrire les itinéraires dans cet exemple, consultez Inscrire les itinéraires de pages.

Navigation vers l’arrière

La navigation vers l’arrière peut être effectuée en spécifiant « .. » comme argument de la méthode GoToAsync :

await Shell.Current.GoToAsync("..");

La navigation vers l’arrière avec .. peut également être combinée avec un itinéraire :

await Shell.Current.GoToAsync("../route");

Dans cet exemple, la navigation vers l’arrière est effectuée, puis la navigation vers l’itinéraire spécifié.

Important

La navigation vers l’arrière et dans un itinéraire spécifié n’est possible que si la navigation vers l’arrière vous place à l’emplacement actuel dans la hiérarchie de routage pour accéder à l’itinéraire spécifié.

De même, il est possible de revenir en arrière plusieurs fois, puis d’accéder à un itinéraire spécifié :

await Shell.Current.GoToAsync("../../route");

Dans cet exemple, la navigation vers l’arrière est effectuée deux fois, puis la navigation vers l’itinéraire spécifié.

En outre, les données peuvent être transmises via les propriétés de requête lors de la navigation vers l’arrière :

await Shell.Current.GoToAsync($"..?parameterToPassBack={parameterValueToPassBack}");

Dans cet exemple, la navigation vers l’arrière est effectuée et la valeur du paramètre de requête est passée au paramètre de requête de la page précédente.

Notes

Les paramètres de requête peuvent être ajoutés à toute demande de navigation descendante.

Pour plus d’informations sur la transmission de données lors de la navigation, consultez Passer des données.

Itinéraires non valides

Les formats d’itinéraires suivants ne sont pas valides :

Format Explication
//page ou ///page Actuellement, les itinéraires globaux ne peuvent pas représenter la seule page de la pile de navigation. Par conséquent, l’acheminement absolu pour les itinéraires globaux n’est pas pris en charge.

L’utilisation de ces formats de route entraîne la levée d’un Exception .

Avertissement

La tentative d’accéder à un itinéraire inexistant lève une exception ArgumentException.

Débogage de la navigation

Certaines des classes Shell comportent l’élément DebuggerDisplayAttribute, qui spécifie comment le débogueur affiche une classe ou un champ. Cela peut faciliter le débogage des demandes de navigation en affichant les données relatives à la demande de navigation. Par exemple, la capture d’écran suivante montre les propriétés CurrentItem et CurrentState de l’objet Shell.Current :

Capture d’écran du débogueur

Dans cet exemple, la propriété CurrentItem de type FlyoutItem affiche le titre et l’itinéraire de l’objet FlyoutItem. De même, la propriété CurrentState de type ShellNavigationState affiche l’URI de l’itinéraire affiché dans l’application Shell.

La Tab classe définit une Stack propriété, de type IReadOnlyList<Page>, qui représente la pile de navigation actuelle dans le Tab. La classe fournit également les méthodes de navigation substituables suivantes :

  • GetNavigationStack, retourne IReadOnlyList<Page>, la pile de navigation actuelle.
  • OnInsertPageBefore, appelée lorsque INavigation.InsertPageBefore est appelée.
  • OnPopAsync, retourne Task<Page> et est appelée lorsque INavigation.PopAsync est appelée.
  • OnPopToRootAsync, retourne Task et est appelée lorsque INavigation.OnPopToRootAsync est appelée.
  • OnPushAsync, retourne Task et est appelée lorsque INavigation.PushAsync est appelée.
  • OnRemovePage, appelée lorsque INavigation.RemovePage est appelée.

L’exemple suivant montre comment remplacer la OnRemovePage méthode :

public class MyTab : Tab
{
    protected override void OnRemovePage(Page page)
    {
        base.OnRemovePage(page);

        // Custom logic
    }
}

Dans cet exemple, MyTab les objets doivent être consommés dans votre hiérarchie visuelle Shell au lieu d’objets Tab .

La Shell classe définit l’événement Navigating , qui est déclenché lorsque la navigation est sur le point d’être effectuée, en raison de la navigation par programmation ou de l’interaction de l’utilisateur. L’objet ShellNavigatingEventArgs qui accompagne l’événement Navigating fournit les propriétés suivantes :

Propriété Type Description
Current ShellNavigationState URI de la page actuelle.
Source ShellNavigationSource Le type de navigation qui s’est produit.
Target ShellNavigationState URI représentant la destination de la navigation.
CanCancel bool Valeur indiquant s’il est possible d’annuler la navigation.
Cancelled bool Valeur indiquant si la navigation a été annulée.

En outre, la ShellNavigatingEventArgs classe fournit une Cancel méthode qui peut être utilisée pour annuler la navigation et une GetDeferral méthode qui retourne un ShellNavigatingDeferral jeton qui peut être utilisé pour terminer la navigation. Pour plus d’informations sur le report de navigation, consultez Report de navigation.

La Shell classe définit également l’événement Navigated , qui est déclenché lorsque la navigation est terminée. L’objet ShellNavigatedEventArgs qui accompagne l’événement Navigated fournit les propriétés suivantes :

Propriété Type Description
Current ShellNavigationState URI de la page actuelle.
Previous ShellNavigationState URI de la page précédente.
Source ShellNavigationSource Le type de navigation qui s’est produit.

Important

La OnNavigating méthode est appelée lorsque l’événement Navigating se déclenche. De même, la OnNavigated méthode est appelée lorsque l’événement Navigated se déclenche. Les deux méthodes peuvent être remplacées dans votre Shell sous-classe pour intercepter les demandes de navigation.

Les classes ShellNavigatedEventArgs et ShellNavigatingEventArgs comportent des propriétés Source de type ShellNavigationSource. Cette énumération fournit les valeurs suivantes :

  • Unknown
  • Push
  • Pop
  • PopToRoot
  • Insert
  • Remove
  • ShellItemChanged
  • ShellSectionChanged
  • ShellContentChanged

Par conséquent, la navigation peut être interceptée dans un OnNavigating remplacement et des actions peuvent être effectuées en fonction de la source de navigation. Par exemple, le code suivant montre comment annuler la navigation en amont si les données sur la page ne sont pas enregistrées :

protected override void OnNavigating(ShellNavigatingEventArgs args)
{
    base.OnNavigating(args);

    // Cancel any back navigation.
    if (args.Source == ShellNavigationSource.Pop)
    {
        args.Cancel();
    }
// }

La navigation dans l’interpréteur de commandes peut être interceptée et terminée ou annulée en fonction du choix de l’utilisateur. Pour ce faire, vous pouvez remplacer la OnNavigating méthode dans votre Shell sous-classe et appeler la GetDeferral méthode sur l’objet ShellNavigatingEventArgs . Cette méthode retourne un ShellNavigatingDeferral jeton qui a une Complete méthode, qui peut être utilisée pour effectuer la demande de navigation :

public MyShell : Shell
{
    // ...
    protected override async void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);

        ShellNavigatingDeferral token = args.GetDeferral();

        var result = await DisplayActionSheet("Navigate?", "Cancel", "Yes", "No");
        if (result != "Yes")
        {
            args.Cancel();
        }
        token.Complete();
    }    
}

Dans cet exemple, une feuille d’action s’affiche et invite l’utilisateur à effectuer la demande de navigation ou à l’annuler. La navigation est annulée en appelant la Cancel méthode sur l’objet ShellNavigatingEventArgs . La navigation s’effectue en appelant la Complete méthode sur le ShellNavigatingDeferral jeton récupéré par la GetDeferral méthode sur l’objet ShellNavigatingEventArgs .

Avertissement

La GoToAsync méthode lève un InvalidOperationException si un utilisateur tente de naviguer alors qu’un report de navigation est en attente.

Passer des données

Les données peuvent être passées en tant que paramètres de requête lors de l’exécution d’une navigation par programmation basée sur l’URI. Pour ce faire, ajoutez ? après un itinéraire, suivi d’un ID de paramètre de requête, =et d’une valeur. Par exemple, le code suivant est exécuté dans l’exemple d’application lorsqu’un utilisateur sélectionne un éléphant sur la page ElephantsPage :

async void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string elephantName = (e.CurrentSelection.FirstOrDefault() as Animal).Name;
    await Shell.Current.GoToAsync($"elephantdetails?name={elephantName}");
}

Cet exemple de code extrait l’éléphant actuellement sélectionné dans CollectionView et accède à l’itinéraire elephantdetails en passant elephantName comme paramètre de requête.

Il existe deux approches pour recevoir des données de navigation :

  1. La classe qui représente la page vers laquelle vous accédez, ou la classe de la page BindingContext, peut être décorée avec un QueryPropertyAttribute pour chaque paramètre de requête. Pour plus d’informations, consultez Traiter les données de navigation à l’aide des attributs de propriété de requête.
  2. La classe qui représente la page vers laquelle vous accédez, ou la classe de la page , peut implémenter l’interfaceBindingContextIQueryAttributable. Pour plus d’informations, consultez Traiter les données de navigation à l’aide d’une méthode unique.

Traiter les données de navigation à l’aide d’attributs de propriété de requête

Les données de navigation peuvent être reçues en décorant la classe de réception avec un QueryPropertyAttribute pour chaque paramètre de requête :

[QueryProperty(nameof(Name), "name")]
public partial class ElephantDetailPage : ContentPage
{
    public string Name
    {
        set
        {
            LoadAnimal(value);
        }
    }
    ...

    void LoadAnimal(string name)
    {
        try
        {
            Animal animal = ElephantData.Elephants.FirstOrDefault(a => a.Name == name);
            BindingContext = animal;
        }
        catch (Exception)
        {
            Console.WriteLine("Failed to load animal.");
        }
    }    
}

Le premier argument de spécifie QueryPropertyAttribute le nom de la propriété qui recevra les données, le deuxième argument spécifiant l’ID du paramètre de requête. Par conséquent, le QueryPropertyAttribute dans l’exemple ci-dessus spécifie que la Name propriété recevra les données passées dans le name paramètre de requête à partir de l’URI dans l’appel de méthode GoToAsync . La Name propriété setter appelle la LoadAnimal méthode pour récupérer l’objet Animal pour le nameet le définit comme le BindingContext de la page.

Notes

Les valeurs des paramètres de requête reçues via le QueryPropertyAttribute sont automatiquement décodées par l’URL.

Traiter les données de navigation à l’aide d’une seule méthode

Les données de navigation peuvent être reçues en implémentant l’interface IQueryAttributable sur la classe de réception. L’interface IQueryAttributable spécifie que la classe d’implémentation doit implémenter la ApplyQueryAttributes méthode . Cette méthode a un query argument, de type IDictionary<string, string>, qui contient toutes les données passées pendant la navigation. Chaque clé du dictionnaire est un ID de paramètre de requête, sa valeur étant la valeur du paramètre de requête. L’avantage de cette approche est que les données de navigation peuvent être traitées à l’aide d’une seule méthode, ce qui peut être utile lorsque vous avez plusieurs éléments de données de navigation qui nécessitent un traitement dans leur ensemble.

L’exemple suivant montre une classe de modèle de vue qui implémente l’interface IQueryAttributable :

public class MonkeyDetailViewModel : IQueryAttributable, INotifyPropertyChanged
{
    public Animal Monkey { get; private set; }

    public void ApplyQueryAttributes(IDictionary<string, string> query)
    {
        // The query parameter requires URL decoding.
        string name = HttpUtility.UrlDecode(query["name"]);
        LoadAnimal(name);
    }

    void LoadAnimal(string name)
    {
        try
        {
            Monkey = MonkeyData.Monkeys.FirstOrDefault(a => a.Name == name);
            OnPropertyChanged("Monkey");
        }
        catch (Exception)
        {
            Console.WriteLine("Failed to load animal.");
        }
    }
    ...
}

Dans cet exemple, la ApplyQueryAttributes méthode récupère la valeur du paramètre de name requête à partir de l’URI dans l’appel de méthode GoToAsync . Ensuite, la LoadAnimal méthode est appelée pour récupérer l’objet Animal , où il est défini comme valeur de la Monkey propriété qui est liée aux données.

Important

Les valeurs des paramètres de requête reçues via l’interface IQueryAttributable ne sont pas décodées automatiquement par l’URL.

Passer et traiter plusieurs paramètres de requête

Plusieurs paramètres de requête peuvent être passés en les connectant à &. Par exemple, le code suivant passe deux éléments de données :

async void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string elephantName = (e.CurrentSelection.FirstOrDefault() as Animal).Name;
    string elephantLocation = (e.CurrentSelection.FirstOrDefault() as Animal).Location;
    await Shell.Current.GoToAsync($"elephantdetails?name={elephantName}&location={elephantLocation}");
}

Cet exemple de code récupère l’éléphant actuellement sélectionné dans , CollectionViewet accède à l’itinéraire elephantdetails , en passant elephantName et elephantLocation en tant que paramètres de requête.

Pour recevoir plusieurs éléments de données, la classe qui représente la page vers laquelle la navigation est effectuée, ou la classe de la page de BindingContext, peut être décorée avec un QueryPropertyAttribute pour chaque paramètre de requête :

[QueryProperty(nameof(Name), "name")]
[QueryProperty(nameof(Location), "location")]
public partial class ElephantDetailPage : ContentPage
{
    public string Name
    {
        set
        {
            // Custom logic
        }
    }

    public string Location
    {
        set
        {
            // Custom logic
        }
    }
    ...    
}

Dans cet exemple, la classe est décorée avec un QueryPropertyAttribute pour chaque paramètre de requête. La première QueryPropertyAttribute spécifie que la Name propriété recevra les données transmises dans le name paramètre de requête, tandis que la seconde QueryPropertyAttribute spécifie que la Location propriété recevra les données transmises dans le paramètre de location requête. Dans les deux cas, les valeurs des paramètres de requête sont spécifiées dans l’URI de l’appel de GoToAsync méthode.

Vous pouvez également traiter les données de navigation par une seule méthode en implémentant l’interface IQueryAttributable sur la classe qui représente la page vers laquelle la navigation est effectuée, ou la classe pour la page :BindingContext

public class ElephantDetailViewModel : IQueryAttributable, INotifyPropertyChanged
{
    public Animal Elephant { get; private set; }

    public void ApplyQueryAttributes(IDictionary<string, string> query)
    {
        string name = HttpUtility.UrlDecode(query["name"]);
        string location = HttpUtility.UrlDecode(query["location"]);
        ...        
    }
    ...
}

Dans cet exemple, la ApplyQueryAttributes méthode récupère la valeur des paramètres de name requête et location à partir de l’URI dans l’appel de GoToAsync méthode.

Comportement du bouton Précédent

L’apparence et le comportement du bouton Précédent peuvent être redéfinis en définissant la BackButtonBehavior propriété jointe sur un BackButtonBehavior objet. La BackButtonBehavior classe définit les propriétés suivantes :

  • Command, de type ICommand : exécuté lorsque l’utilisateur appuie sur le bouton Précédent.
  • CommandParameter, de type object : paramètre passé à la commande Command.
  • IconOverride, de type ImageSource : icône utilisée pour le bouton Précédent.
  • IsEnabled, de type boolean : indique si le bouton Précédent est activé. La valeur par défaut est true.
  • TextOverride, de type string : texte utilisé pour le bouton Précédent.

Toutes ces propriétés s’appuient sur des objets BindableProperty, ce qui signifie qu’elles peuvent être des cibles de liaisons de données.

Le code suivant montre un exemple de redéfinition de l’apparence et du comportement du bouton Précédent :

<ContentPage ...>    
    <Shell.BackButtonBehavior>
        <BackButtonBehavior Command="{Binding BackCommand}"
                            IconOverride="back.png" />   
    </Shell.BackButtonBehavior>
    ...
</ContentPage>

Le code C# équivalent est :

Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
    Command = new Command(() =>
    {
        ...
    }),
    IconOverride = "back.png"
});

La propriété Command est définie sur un élément ICommand à exécuter lorsque le bouton Précédent est enfoncé, et la propriété IconOverride est définie sur l’icône utilisée pour le bouton Précédent :

Capture d’écran d’une icône de remplacement du bouton Retour de l’interpréteur de commandes, sur iOS et Android