Navegación del shell de .NET MAUI

Browse sample. Examinar la muestra.

El shell .NET Multi-platform App UI (.NET MAUI) incluye una experiencia de navegación basada en URI que usa 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:

  • BackButtonBehavior, de tipo BackButtonBehavior, una propiedad adjunta que define el comportamiento del botón Atrás.
  • CurrentItem, de tipo ShellItem, el valor seleccionado actualmente.
  • CurrentPage, de tipo Page, la página presentada actualmente.
  • CurrentState, de tipo ShellNavigationState, el estado de navegación actual de Shell.
  • Current, de tipo Shell, un alias con el tipo convertido para Application.Current.MainPage.

Las propiedades BackButtonBehavior, CurrentItem y CurrentState están respaldadas por objetos BindableProperty, lo que significa que estas propiedades pueden ser destinos de los 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:

Se puede seguir navegando entre páginas en una aplicación de Shell con la propiedad Navigation. Para obtener más información, consulta Realizar navegación no modal.

Rutas

Para navegar en una aplicación shell, se especifica 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 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

Se pueden definir rutas en objetos FlyoutItem, TabBar, Tab y ShellContent mediante sus propiedades Route:

<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. Pero 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 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 de detalles 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, el registro de las páginas cuyas rutas se han registrado con el método Routing.RegisterRoute se puede cancelar 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 App.Current.MainPage en un objeto Shell o por medio de la propiedad Shell.Current. La navegación se puede realizar entonces llamando al método GoToAsync en el objeto Shell. Este método lleva a una clase 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 actual de navegación del objeto Shell se puede recuperar mediante la propiedad Shell.Current.CurrentState, que incluye el URI de la ruta mostrada en la propiedad Location.

Rutas absolutas

La navegación se puede realizar 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.
/route 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.
//route 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.
///route 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
//page 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 CurrentItem y CurrentState del objeto Shell.Current:

Screenshot of debugger.

En este ejemplo, la propiedad CurrentItem, de tipo FlyoutItem, muestra el título y la ruta de acceso del objeto FlyoutItem. Igualmente, la propiedad CurrentState, de tipo ShellNavigationState, muestra el URI de la ruta mostrada dentro de la aplicación de Shell.

La clase Tab define una propiedad Stack, de tipo IReadOnlyList<Page>, que representa la pila de navegación actual dentro de Tab. La clase también proporciona los siguientes métodos reemplazables de navegación:

  • GetNavigationStack, que devuelve IReadOnlyList<Page>, la pila de navegación actual.
  • OnInsertPageBefore, que se llama cuando se llama a INavigation.InsertPageBefore.
  • OnPopAsync, que devuelve Task<Page> y se llama cuando se llama a INavigation.PopAsync.
  • OnPopToRootAsync, que devuelve Task y se llama cuando se llama a INavigation.OnPopToRootAsync.
  • OnPushAsync, que 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 Type Descripción
Current ShellNavigationState Identificador URI base de la página actual.
Source ShellNavigationSource El tipo de navegación que se ha producido.
Target ShellNavigationState Identificador URI que representa el destino de la navegación.
CanCancel bool Valor que indica si es posible cancelar la navegación.
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 Type Descripción
Current ShellNavigationState Identificador URI base de la página actual.
Previous ShellNavigationState Identificador URI de la página anterior.
Source ShellNavigationSource 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.

Ambas clases, ShellNavigatedEventArgs y ShellNavigatingEventArgs, tienen 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 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

Los datos primitivos se pueden pasar como parámetros de consulta basados en cadenas al realizar la navegación mediante programación basada en URI. Para esto, se anexa ? después de una ruta, seguido de un identificador de parámetro de consulta, = y un valor:

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 se recupera el elefante actualmente seleccionado en CollectionView y se navega a la ruta elephantdetails; además, se pasa elephantName como parámetro de consulta.

Pasar datos de navegación basados en objetos de uso múltiple

Se pueden pasar datos de navegación basados en objetos de uso múltiple con una sobrecarga de GoToAsync que especifica un argumento IDictionary<string, object>:

async void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Animal animal = e.CurrentSelection.FirstOrDefault() as Animal;
    var navigationParameter = new Dictionary<string, object>
    {
        { "Bear", animal }
    };
    await Shell.Current.GoToAsync($"beardetails", navigationParameter);
}

En este ejemplo se recupera el oso seleccionado actualmente en CollectionView, como Animal. El objeto Animal se agrega a Dictionary con la clave Bear. A continuación, se realiza la navegación a la ruta beardetails, con Dictionary que se pasa como parámetro de navegación.

Los datos que se pasan como argumento IDictionary<string, object> se conservan en la memoria durante la vigencia de la página y no se liberan hasta que la página se quita de la pila de navegación. Esto puede ser problemático como se muestra en el escenario siguiente:

  1. Page1 navega a Page2 usando el método GoToAsync y pasando un objeto denominado MyData. A continuación, Page2 recibe MyData como parámetro de consulta.
  2. Page2 navega hasta Page3 usando el método GoToAsync, sin pasar ningún dato.
  3. Page3 navega hacia atrás con el método GoToAsync. A continuación, Page2 recibe MyData de nuevo como parámetro de consulta.

Aunque esto es deseable en muchos escenarios, si no lo deseas, debes borrar el argumento IDictionary<string, object> con el método Clear después de que una página lo reciba por primera vez.

Pasar datos de navegación basados en objetos de uso único

Los datos de navegación basados en objetos de uso único se pueden pasar con una sobrecarga de GoToAsync que especifica un argumento ShellNavigationQueryParameters. El objeto ShellNavigationQueryParameters está diseñado para datos de navegación de uso único que se borran después de que se haya producido la navegación. En el ejemplo siguiente se muestra cómo navegar mientras se pasan datos de uso único:

async void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Animal animal = e.CurrentSelection.FirstOrDefault() as Animal;
    var navigationParameter = new ShellNavigationQueryParameters
    {
        { "Bear", animal }
    };
    await Shell.Current.GoToAsync($"beardetails", navigationParameter);
}

En este ejemplo se recupera el oso seleccionado actualmente en CollectionView, como Animal que se agrega al objeto ShellNavigationQueryParameters. A continuación, se realiza la navegación a la ruta beardetails, con el objeto ShellNavigationQueryParameters que se pasa como parámetro de navegación. Después de que se haya producido la navegación, se borran los datos del objeto ShellNavigationQueryParameters.

Recepción de datos de navegación

Hay dos formas de recibir datos de navegación:

  1. La clase que representa la página a la que se navega, o la clase correspondiente al objeto BindingContext de la página, se puede decorar con un elemento QueryPropertyAttribute por cada parámetro de 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 navega, o la clase correspondiente al objeto BindingContext de la página, puede implementar la interfaz IQueryAttributable. 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 QueryPropertyAttribute para cada parámetro de consulta basado en cadenas y cada parámetro de navegación basado en objetos:

Para recibir datos de navegación, se puede decorar la clase receptora con QueryPropertyAttribute para cada parámetro de consulta basado en cadenas y cada parámetro de navegación basado en objetos o el objeto ShellNavigationQueryParameters:

[QueryProperty(nameof(Bear), "Bear")]
public partial class BearDetailPage : ContentPage
{
    Animal bear;
    public Animal Bear
    {
        get => bear;
        set
        {
            bear = value;
            OnPropertyChanged();
        }
    }

    public BearDetailPage()
    {
        InitializeComponent();
        BindingContext = this;
    }
}

En este ejemplo, 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 lo tanto, QueryPropertyAttribute del ejemplo anterior especifica que la propiedad Bear recibirá los datos pasados al parámetro de navegación Bear en la llamada al método GoToAsync.

Nota:

Los valores de los parámetros de consulta basados en cadenas que se reciben a través de QueryPropertyAttribute se descodifican automáticamente en la 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, object>, que contiene los datos que se pasan durante la navegación. Cada clave del diccionario es un identificador de parámetro de consulta, con su valor correspondiente al objeto que representa los datos. 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, object> query)
    {
        Monkey = query["Monkey"] as Animal;
        OnPropertyChanged("Monkey");
    }
    ...
}

En este ejemplo, el método ApplyQueryAttributes recupera el objeto que corresponde a la clave Monkey del diccionario query, que se pasó como argumento a la llamada al método GoToAsync.

Importante

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

Pasar y procesar varios elementos de datos

Se pueden pasar varios parámetros de consulta basados en cadenas 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 BindingContext de la página, se puede decorar con QueryPropertyAttribute por cada parámetro de consulta basado en cadenas:

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

Opcionalmente, para procesar datos de navegación mediante un único método, se puede implementar la interfaz IQueryAttributable en la clase que representa la página a la que se navega, o la clase correspondiente al objeto BindingContext de la página:

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

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

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.

Nota:

Los parámetros de consulta basados en cadenas y los parámetros de navegación basados en objetos se pueden pasar simultáneamente al realizar la navegación basada en rutas.

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:

  • Command, de tipo ICommand, que se ejecuta cuando se presiona el botón Atrás.
  • CommandParameter, de tipo object, que es el parámetro que se pasa al objeto Command.
  • IconOverride, de tipo ImageSource, el icono usado para el botón Atrás.
  • IsEnabled, de tipo boolean, indica si se ha habilitado el botón Atrás. El valor predeterminado es true.
  • IsVisible, de tipo boolean, indica si el botón Atrás está visible. El valor predeterminado es true.
  • TextOverride, de tipo string, el texto usado para el botón Atrás.

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>

La propiedad Command se establece en ICommand para ejecutarse cuando se presiona el botón Atrás y la propiedad IconOverride se establece en el icono que se usa para el botón Atrás:

Screenshot of a Shell back button icon override.