Shell Quick Tip – Passing Data When Navigating

Avatar

James

Every mobile application needs navigation. Xamarin.Forms Shell offers built-in route based navigation to enable easy navigation to and from pages in your application. Additionally, since it is based on a route schema, you can navigate using absolute or relative routes that will even inflate a full back stack.

In most cases, relative route navigation is best as you are pushing a unique page onto the stack. Let’s say you are on a monkeys page and wanted to navigate to the details. You would use a simple relative route to navigate:

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

2 screens from an app showing navigation from the root to details page

Now, to build up a navigation stack for deep linking you can use absolute routes. This will take you to the monkeys route and then push the details page.

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

This is helpful. However, in both cases it would be great is if you could pass in data to the details page to tell it to display specific monkeys details. Read on for a full walkthrough of how to pass data from one page to another.

Passing dData

What happens when you want to pass data from one page to another? Well that is where Shell’s built in Query Parameters come in. It enables you to seamlessly pass data around your application. Let’s walk through a simple app that increase the count on the page and passes that data to the next page when the app navigates:

Image Pass Data with Shell Query Parameter

Look at the code to setup the first page. It is a relatively simple user interface with a few buttons and label to display the count:

<StackLayout VerticalOptions="Center">
    <Label x:Name="LabelCount" Text="{Binding Count, StringFormat='You clicked {0}'}"/>
    <Button Text="Click Me" x:Name="ButtonClick" Clicked="ButtonClick_Clicked"/>
    <Button Text="Navigate" x:Name="ButtonNavigate" Clicked="ButtonNavigate_Clicked"/>
</StackLayout>

In the code behind for the page when we click the button, it increase the count and notifies the user interface.

public int Count { get; set; }
        
void ButtonClick_Clicked(object sender, EventArgs e)
{
    Count++;
    OnPropertyChanged(nameof(Count));
}

Navigating To Page2

Now, let’s say that we want to navigate to the second page, in this case Page2. We would first register our route in our Shell:

Routing.RegisterRoute(nameof(Page2), typeof(Page2));

Then we can navigate to it using GoToAsync on the current Shell.

await Shell.Current.GoToAsync(nameof(Page2));

We want to pass the current count, so we will use a query parameter on our path. This follows standard Uri routes such as path?param1=hello&param2=world. So, to pass the count we will navigate passing a parameter named count. Any data that is passed is automatically encoded for you.

async void ButtonNavigate_Clicked(object sender, EventArgs e)
{
    await Shell.Current.GoToAsync($"{nameof(Page2)}?Count={Count}");
}

Parsing Parameters

Now that we have passed the count using the parameter, we must receive it on the second page. You can do this either in the code behind of the page that you are navigating to, or to the BindingContext of the page such as a view model. The first thing to do is to add a public property that Xamarin.Forms Shell will call the set on. Here, we will create another Count property that is a string and when we set the value we will call UnescapeDataString as a best practice.

string count = "";
public string Count
{
    get => count;
    set
    {
        count = Uri.UnescapeDataString(value ?? string.Empty);
        OnPropertyChanged();
    }
}

Lastly, add a QueryProperty that tells Xamarin.Forms Shell the property to set the parameter name to parse. Here, we will set the Count property for the count parameter that we passed.

[QueryProperty(nameof(Count), nameof(Count))]
public partial class Page2 : ContentPage
{
    //...
}

In this example, we only passed one parameter. However, you can add as many QueryProperty attributes to the top of your class as you would like.

Deep Linking

Combining route based navigation with query properties can be extremely powerful when creating apps that deep link from the web or custom data schemes. For example in the application Island Tracker, a custom data scheme is used to create a link that the app can use to send friend requests. Here is an example of the deep link that a user would click:

acislandtracker://friends/invite?id=a3be899c-41df-4ce6-8ca7-26b0642efcde&name=James

When it is clicked, Xamarin.Forms will activate the app using the AppLink API.

protected override async void OnAppLinkRequestReceived(Uri uri)
{
    await Shell.Current.GoToAsync($"//{uri.Host}/{uri.PathAndQuery}");
}

From there, Shell will ensure the friend page is navigated to and then it will navigate to the invite page. If navigation to the friend page first was not the intent, simply pass in the full uri to Shell. It takes care of the rest to open the invite page.

Image Deep Link into iOS Application with Query Property

Learn More

To learn more about navigation with Xamarin.Forms Shell and more information about using QueryProperty attributes, browse through our full documentation on Shell navigation. You can also grab the source code for this sample on GitHub. Want more Xamarin.Forms? Checkout our Xamarin.Forms 101 series on Channel 9.

5 comments

Leave a comment