Navegación en Xamarin.Forms Shell

Ejemplo de descarga Descarga del ejemplo

Xamarin.Forms Shell incluye una experiencia de navegación basada en el URI que emplea rutas para navegar a cualquier página de la aplicación, sin tener que seguir una jerarquía de navegación establecida. También ofrece la posibilidad de navegar hacia atrás sin tener que visitar todas las páginas de la pila de navegación.

La clase Shell define las siguientes propiedades relacionadas con la navegación:

Las propiedades BackButtonBehavior , BackButtonBehavior Xamarin_Forms _Shell_CurrentItem" data-linktype="absolute-path">y CurrentItem Xamarin_Forms _Shell_CurrentState" data-linktype="absolute-path">CurrentStateBindableProperty están copiadas por objetos , lo que significa que estas propiedades pueden ser destinos de enlaces de datos.

La navegación se realiza mediante la invocación del método GoToAsync, desde la clase Shell. Cuando la navegación está a punto de realizarse, se activa un evento Navigating y, cuando finaliza, se activa un evento Navigated.

Nota

Todavía se puede realizar la navegación entre páginas de una aplicación de Shell mediante la propiedad Xamarin_Forms _NavigableElement_Navigation" data-linktype="absolute-path"> Navigation. Para más información, consulte Navegación jerárquica.

Rutas

La navegación se realiza en una aplicación de Shell mediante la especificación de un URI al que navegar. Los URI de navegación pueden tener tres componentes:

  • Una ruta, que define la ruta de acceso al contenido que existe como parte de la jerarquía visual de Shell.
  • Una página. Las páginas que no existen en la jerarquía visual de Shell se pueden insertar en la pila de navegación desde cualquier lugar dentro de una aplicación de Shell. Por ejemplo, una página de detalles no se definirá en la jerarquía visual de Shell, pero se puede insertar en la pila de navegación si es necesario.
  • Uno o varios parámetros de consulta. Los parámetros de consulta son parámetros que se pueden pasar a la página de destino durante la navegación.

Cuando un URI de navegación incluye los tres componentes, la estructura es: //route/page?queryParameters

Registro de rutas

Las rutas se pueden definir en FlyoutItem objetos , , y a través de sus TabBarTabShellContentRoute propiedades:

<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>

Nota

Todos los elementos de la jerarquía de Shell tienen asociada una ruta. Si no se establece una ruta, se genera una en tiempo de ejecución. Sin embargo, no se garantiza que las rutas generadas sean coherentes entre distintas sesiones de aplicación.

En el ejemplo anterior se crea la siguiente jerarquía de ruta, que se puede usar en la navegación mediante programación:

animals
  domestic
    cats
    dogs
  monkeys
  elephants
  bears
about

Para desplazarse al objeto ShellContent de la ruta dogs, el URI de la ruta absoluta es //animals/domestic/dogs. Igualmente, para desplazarse al objeto ShellContent de la ruta about, el URL de la ruta absoluta es //about.

Advertencia

Si se detecta una ruta duplicada, se produce una excepción ArgumentException al inicio de la aplicación. También se producirá esta excepción si dos o más rutas del mismo nivel de la jerarquía comparten el nombre de ruta.

Registro de rutas de la página de detalles

En el constructor de subclases de Shell, o en cualquier otra ubicación que se ejecute antes de invocar una ruta, se pueden registrar explícitamente rutas adicionales para cualquier página que no esté representada en la jerarquía visual de Shell. Esto se realiza mediante el método 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));

En este ejemplo se registran como rutas páginas de detalles que no están definidas en la subclase Shell. Se puede navegar después a estas páginas desde cualquier lugar de la aplicación con la navegación basada en URI. Las rutas de estas páginas se conocen como rutas globales.

Advertencia

Se producirá una excepción ArgumentException si el método Routing.RegisterRoute intenta registrar la misma ruta en dos o más tipos diferentes.

Como alternativa, se pueden registrar las páginas en diferentes jerarquías de ruta:

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));

En este ejemplo se habilita la navegación contextual por las páginas, donde la navegación a la ruta details desde la página de la ruta monkeys muestra MonkeyDetailPage. De forma similar, al desplazarse a la ruta details desde la página de la ruta elephants se muestra ElephantDetailPage. Para obtener más información, consulte Navegación contextual.

Nota

Si es necesario, se puede cancelar el registro de las páginas cuyas rutas se han registrado con el método Routing.RegisterRoute, con el método Routing.UnRegisterRoute.

Realización de la navegación

Para realizar la navegación, se debe obtener primero una referencia a la subclase Shell. Esta referencia se puede obtener mediante la conversión de la propiedad en un objeto o a través de la propiedad App.Current.MainPageShell Xamarin_Forms App.Current.MainPage _Shell_Current" data-linktype="absolute-path">. Shell.Current Luego, se puede realizar la navegación mediante la llamada al método GoToAsync en el objeto Shell. Este método lleva a ShellNavigationState y devuelve un objeto Task que se completa una vez completada la animación de navegación. El objeto ShellNavigationState se construye mediante el método GoToAsync, desde una propiedad string o Uri, y tiene su propiedad Location establecida en el argumento string o Uri.

Importante

Cuando se navega a una ruta de la jerarquía visual de Shell, no se crea una pila de navegación. Sin embargo, cuando se navega a una página que no está en la jerarquía visual de Shell, se crea una pila de navegación.

El estado de navegación actual del objeto se puede recuperar a través de la propiedad ShellShell Xamarin_Forms _Shell_CurrentState" data-linktype="absolute-path">, Shell.Current.CurrentState que Location incluye el URI de la ruta mostrada en la propiedad .

Rutas absolutas

Se puede realizar la navegación mediante la especificación de un URI absoluto válido como argumento del método GoToAsync:

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

En este ejemplo se navega a la página de la ruta monkeys, donde dicha ruta se define en un objeto ShellContent. El objeto ShellContent que representa la ruta monkeys es un elemento secundario de un objeto FlyoutItem, cuya ruta es animals.

Rutas relativas

La navegación se puede realizar también mediante la especificación de un URI relativo válido como argumento del método GoToAsync. El sistema de enrutamiento intenta hacer coincidir el URI con un objeto ShellContent. Por lo tanto, si todas las rutas de una aplicación son únicas, la navegación se puede realizar con solo especificar el nombre de ruta único como un URI relativo.

Se admiten los formatos siguientes de ruta relativa:

Formato Descripción
route En la jerarquía de ruta se buscará la ruta especificada, hacia arriba desde la posición actual. La página que coincida se insertará en la pila de navegación.
// La jerarquía de ruta se buscará a partir de la ruta especificada, hacia abajo desde la posición actual. La página que coincida se insertará en la pila de navegación.
//// En la jerarquía de ruta se buscará la ruta especificada, hacia arriba desde la posición actual. La página que coincida reemplazará la pila de navegación.
////// En la jerarquía de ruta se buscará la ruta especificada, hacia abajo desde la posición actual. La página que coincida reemplazará la pila de navegación.

En el ejemplo siguiente se navega a la página de la ruta monkeydetails:

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

En este ejemplo, la ruta monkeyDetails se busca hacia arriba en la jerarquía hasta que se encuentra la página que coincide. Cuando se encuentra, se inserta en la pila de navegación.

Navegación contextual

Las rutas relativas permiten la navegación contextual. Por ejemplo, considere la siguiente jerarquía de ruta:

monkeys
  details
bears
  details

Cuando se muestra la página registrada para la ruta monkeys, al navegar a la ruta details se mostrará la página registrada para la ruta monkeys/details. Igualmente, cuando se muestra la página registrada para la ruta bears, al navegar a la ruta details se mostrará la página registrada para la ruta bears/details. Para información sobre cómo registrar las rutas en este ejemplo, consulte Registro de rutas de página.

Navegación hacia atrás

La navegación hacia atrás se puede llevar a cabo especificando ".." como argumento en el método GoToAsync:

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

La navegación hacia atrás con ".." también se puede combinar con una ruta:

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

En este ejemplo, se realiza la navegación hacia atrás y, después, se navega a la ruta especificada.

Importante

Desplazarse hacia atrás y luego a una ruta especificada solo es posible si la navegación hacia atrás sitúa al usuario en la ubicación actual en la jerarquía de rutas para navegar a la ruta especificada.

Del mismo modo, es posible desplazarse hacia atrás varias veces y, seguidamente, navegar a una ruta especificada:

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

En este ejemplo, la navegación hacia atrás se realiza dos veces y, después, se navega a la ruta especificada.

Además, los datos se pueden pasar a través de las propiedades de consulta al navegar hacia atrás:

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

En este ejemplo, se realiza la navegación hacia atrás y el valor del parámetro de consulta se pasa al parámetro de consulta en la página anterior.

Nota

Los parámetros de consulta se pueden anexar a cualquier solicitud de navegación hacia atrás.

Para obtener más información sobre cómo pasar datos al navegar, vea Pasar datos.

Rutas no válidas

Los siguientes formatos de ruta no son válidos:

Formato Explicación
//// o ///page Actualmente, las rutas globales no pueden ser la única página en la pila de navegación. Por lo tanto, no se admite el enrutamiento absoluto a rutas globales.

El uso de estos formatos de ruta dará como resultado una excepción Exception.

Advertencia

Al intentar navegar a una ruta inexistente, se producirá una excepción ArgumentException.

Depuración de la navegación

Algunas de las clases de Shell se representan con DebuggerDisplayAttribute, que especifica cómo el depurador muestra una clase o campo. Esto puede ayudar a depurar las solicitudes de navegación puesto que se muestran los datos relacionados con la solicitud de navegación. Por ejemplo, en la captura de pantalla siguiente se muestran las propiedades data-linktype="absolute-path">CurrentItem y Xamarin_Forms CurrentItem _Shell_CurrentState" data-linktype="absolute-path">CurrentState de Xamarin_Forms _Shell_Current" data-linktype="absolute-path">Shell.Current object:

Captura de pantalla del depurador del

En este ejemplo, la propiedad Xamarin_Forms _Shell_CurrentItem" data-linktype="absolute-path">, de tipo , muestra el título y la ruta CurrentItem del FlyoutItemFlyoutItem objeto. De forma similar, la propiedad Xamarin_Forms _Shell_CurrentState" data-linktype="absolute-path">, de tipo , muestra el URI de la ruta mostrada dentro de la aplicación CurrentStateShellNavigationState shell.

La Tab clase define una propiedad Xamarin_Forms Tab _ShellSection_Stack" data-linktype="absolute-path">, StackIReadOnlyList<Page> de Tab tipo , que representa la pila de navegación actual dentro de . La clase también proporciona los siguientes métodos de navegación reemplazables:

  • GetNavigationStack, devuelve IReadOnlyList<Page> , la pila de navegación actual.
  • OnInsertPageBefore, que se llama cuando se llama a INavigation.InsertPageBefore.
  • OnPopAsync, devuelve Task<Page>, y se llama cuando se llama a INavigation.PopAsync.
  • OnPopToRootAsync, devuelve Task, y se llama cuando se llama a INavigation.OnPopToRootAsync.
  • OnPushAsync, devuelve Task, y se llama cuando se llama a INavigation.PushAsync.
  • OnRemovePage, que se llama cuando se llama a INavigation.RemovePage.

En el ejemplo siguiente se muestra cómo se invalida el método OnRemovePage:

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

        // Custom logic
    }
}

En este ejemplo, los objetos MyTab se deben consumir en la jerarquía visual de Shell en lugar de los objetos Tab.

La clase Shell define un evento Navigating, que se desencadena cuando está a punto de realizarse la navegación, ya sea debido a la navegación mediante programación o a la interacción del usuario. El objeto ShellNavigatingEventArgs que acompaña al evento Navigating proporciona las siguientes propiedades:

Propiedad. Tipo Descripción
_ShellNavigatingEventArgs_Current" data-linktype="absolute-path">Current ShellNavigationState Identificador URI de la página actual.
Xamarin_Forms _ShellNavigatingEventArgs_Source" data-linktype="absolute-path">Source ShellNavigationSource El tipo de navegación que se ha producido.
Xamarin_Forms _ShellNavigatingEventArgs_Target" data-linktype="absolute-path">Target ShellNavigationState Identificador URI que representa el destino de la navegación.
Xamarin_Forms _ShellNavigatingEventArgs_CanCancel" data-linktype="absolute-path">CanCancel bool Valor que indica si es posible cancelar la navegación.
Xamarin_Forms _ShellNavigatingEventArgs_Cancelled" data-linktype="absolute-path">Cancelled bool Valor que indica si la navegación se ha cancelado.

Además, la clase ShellNavigatingEventArgs proporciona un método Cancel, que se puede usar para cancelar la navegación, y un método GetDeferral, que devuelve un token de ShellNavigatingDeferral que se puede usar para completar la navegación. Para obtener más información sobre el aplazamiento de la navegación, vea Aplazamiento de navegación.

La clase Shell también define un evento Navigated, que se desencadena cuando se ha completado la navegación. El objeto ShellNavigatedEventArgs que acompaña al evento Navigated proporciona las siguientes propiedades:

Propiedad. Tipo Descripción
Xamarin_Forms _ShellNavigatedEventArgs_Current" data-linktype="absolute-path">Current ShellNavigationState Identificador URI de la página actual.
Xamarin_Forms _ShellNavigatedEventArgs_Previous" data-linktype="absolute-path">Previous ShellNavigationState Identificador URI de la página anterior.
Xamarin_Forms _ShellNavigatedEventArgs_Source" data-linktype="absolute-path">Source ShellNavigationState El tipo de navegación que se ha producido.

Importante

Se llama al método OnNavigating cuando se genera el evento Navigating. Del mismo modo, se llama al método OnNavigated cuando se genera el evento Navigated. Ambos métodos se pueden invalidar en la subclase Shell para interceptar las solicitudes de navegación.

Las clases ShellNavigatedEventArgs y ShellNavigatingEventArgs tienen ambas propiedades Source, de tipo ShellNavigationSource. Esta enumeración proporciona los valores siguientes:

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

Por lo tanto, se puede interceptar la navegación con una invalidación de OnNavigating y se pueden realizar acciones en función del origen de navegación. Por ejemplo, el código siguiente muestra cómo cancelar la navegación hacia atrás si no se han guardado los datos de la página:

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

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

La navegación de shell se puede interceptar y completar, o bien cancelar, según lo que elija el usuario. Esto se puede conseguir invalidando el método OnNavigating de la subclase Shell y, después, llamando al método GetDeferral en el objeto ShellNavigatingEventArgs. Este método devuelve un token de ShellNavigatingDeferral que tiene un método Complete, que se puede usar para completar la solicitud de navegación:

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();
    }    
}

En este ejemplo, se muestra una hoja de acción que invita al usuario a completar la solicitud de navegación o cancelarla. La navegación se cancela invocando el método Cancel en el objeto ShellNavigatingEventArgs. La navegación se completa invocando el método Complete en el token de ShellNavigatingDeferral obtenido mediante el método GetDeferral en el objeto ShellNavigatingEventArgs.

Advertencia

El método GoToAsync generará una excepción InvalidOperationException si un usuario intenta navegar mientras hay un aplazamiento de navegación pendiente.

Pasar datos

Al realizar la navegación mediante programación basada en URI, los datos pueden pasarse como parámetros de consulta. Esto se consigue anexando ? después de una ruta, seguido de un identificador de parámetro de consulta, =, y un valor. Por ejemplo, el código siguiente se ejecuta en la aplicación de ejemplo cuando un usuario selecciona un elefante en ElephantsPage:

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

En este ejemplo de código se recupera el elefante actualmente seleccionado en CollectionView y se realiza el desplazamiento a la ruta elephantdetails; además, se pasa elephantName como parámetro de consulta.

Hay dos formas de recibir datos de navegación:

  1. La clase que representa la página a la que se va a navegar, o la clase para la clase de datos Xamarin_Forms _BindableObject_BindingContext" de la página, data-linktype="absolute-path">, se puede decorar con un para cada parámetro de BindingContextQueryPropertyAttribute consulta. Para obtener más información, vea Procesamiento de datos de navegación mediante atributos de propiedad de consulta.
  2. La clase que representa la página a la que se va a navegar, o la clase de la clase de Xamarin_Forms _BindableObject_BindingContext" de la página data-linktype="absolute-path">BindingContext , puede implementar la IQueryAttributable interfaz . Para obtener más información, vea Procesamiento de datos de navegación mediante un único método.

Procesamiento de datos de navegación mediante atributos de propiedad de consulta

Para recibir datos de navegación, se puede decorar la clase receptora con un objeto QueryPropertyAttribute por cada parámetro de consulta:

[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.");
        }
    }    
}

El primer argumento de QueryPropertyAttribute especifica el nombre de la propiedad que recibirá los datos, mientras que el segundo argumento especifica el identificador del parámetro de consulta. Por tanto, el elemento QueryPropertyAttribute del ejemplo anterior especifica que la propiedad Name recibirá los datos pasados al parámetro de consulta name del URI en la llamada al método GoToAsync. El establecedor de propiedades llama al método para recuperar el objeto para y lo establece como el valor de NameLoadAnimal Xamarin_Forms AnimalnameName _BindableObject_BindingContext" data-linktype="absolute-path">de BindingContext la página.

Nota

Los valores de parámetro de consulta que se reciben a través de QueryPropertyAttribute se descodifican automáticamente como dirección URL.

Procesamiento de datos de navegación mediante un único método

Para recibir datos de navegación, se puede implementar la interfaz IQueryAttributable en la clase receptora. La interfaz IQueryAttributable especifica que la clase encargada de la implementación debe implementar el método ApplyQueryAttributes. Este método tiene un argumento query, de tipo IDictionary<string, string>, que contiene los datos que se pasan durante la navegación. Cada clave del diccionario es un identificador de parámetro de consulta, y su valor es el valor del parámetro de consulta. La ventaja de usar este método es que los datos de navegación se pueden procesar con un único método, lo que puede resultar útil cuando hay varios elementos de datos de navegación que deben procesarse como un todo.

En el siguiente ejemplo se muestra una clase de modelo de vista que implementa la interfaz 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.");
        }
    }
    ...
}

En este ejemplo, el método ApplyQueryAttributes recupera el valor del parámetro de consulta name del URI incluido en la llamada de método GoToAsync. Tras ello, se llama al método LoadAnimal para recuperar el objeto Animal, donde se establece como el valor de la propiedad Monkey a la que se enlazan datos.

Importante

Los valores de parámetro de consulta que se reciben a través de la interfaz IQueryAttributable no se descodifican automáticamente como dirección URL.

Paso y procesamiento de varios parámetros de consulta

Se pueden pasar varios parámetros de consulta conectándolos con &. Por ejemplo, el código siguiente pasa dos elementos de datos:

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}");
}

En este ejemplo de código se recupera el elefante actualmente seleccionado en CollectionView y se navega a la ruta elephantdetails; además, se pasan elephantName y elephantLocation como parámetros de consulta.

Para recibir varios elementos de datos, la clase que representa la página a la que se navega o la clase para el parámetro de datos Xamarin_Forms _BindableObject_BindingContext" de la página, data-linktype="absolute-path">, se puede decorar con un para cada BindingContext parámetro de QueryPropertyAttribute consulta:

[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
        }
    }
    ...    
}

En este ejemplo, la clase se decora con un objeto QueryPropertyAttribute para cada parámetro de consulta. El primer objeto QueryPropertyAttribute especifica que la propiedad Name recibirá los datos pasados en el parámetro de consulta name, mientras que el segundo objeto QueryPropertyAttribute especifica que la propiedad Location recibirá los datos pasado en el parámetro de consulta location. En ambos casos, los valores de los parámetros de consulta se especifican en el URI en la llamada al método GoToAsync.

Como alternativa, los datos de navegación se pueden procesar mediante un único método mediante la implementación de la interfaz en la clase que representa la página a la que se va a navegar, o la clase de la página IQueryAttributableIQueryAttributable Xamarin_Forms _BindableObject_BindingContext" data-linktype="absolute-path">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"]);
        ...        
    }
    ...
}

En este ejemplo, el método ApplyQueryAttributes recupera el valor de los parámetros de consulta name y location del URI incluido en la llamada de método GoToAsync.

Comportamiento del botón Atrás

La apariencia y el comportamiento del botón Atrás se pueden volver a definir estableciendo la propiedad adjunta BackButtonBehavior en un objeto BackButtonBehavior. La clase BackButtonBehavior define las propiedades siguientes:

Todas estas propiedades están respaldados por objetos BindableProperty, lo que significa que las propiedades pueden ser destinos de los enlaces de datos.

En el código siguiente se muestra un ejemplo de cómo volver a definir la apariencia y el comportamiento del botón Atrás:

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

El código de C# equivalente es el siguiente:

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

La propiedad Xamarin_Forms _BackButtonBehavior_Command" data-linktype="absolute-path">se establece en que se ejecutará cuando se presione el botón Atrás y la propiedad se establece en el icono que se usa para el Command botón ICommandIconOverride Atrás:

Captura de pantalla de la invalidación de un icono de botón Atrás de Shell en iOS y Android