user18972374
user18972374

Reputation:

Xamarin - How to pass parameters with shell navigation

I have been searching everywhere how to achieve passing parameters with shell navigation but I can't get this to work.

This is the line where I navigate to my InvoicePage

await Shell.Current.GoToAsync($"//main/InvoicePage?total ={ lblTotalCart.Text.Trim('€')}");

What I want is to be able to retrieve the value on my View Model but I'm trying at least on my ContentPage and it is not working.

[XamlCompilation(XamlCompilationOptions.Compile)]
    [QueryProperty("Total", "total")]
    public partial class InvoicePage : ContentPage
    {
        string total;
        public string Total
        {
            set
            {
                total = Uri.UnescapeDataString(value ?? string.Empty);
                OnPropertyChanged();
            }
            get
            {
                return total;
            }           

        }

        public InvoicePage()
        {
            InitializeComponent();

            BindingContext = new InvoiceViewModel(Total);
        }

Tried the same on my ViewModel and it is also not working.

Here is my View. I just have a Label to test it

<?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:viewmodels="clr-namespace:AppCrijoya.ViewModels"
             x:Class="AppCrijoya.Views.InvoicePage"
             x:DataType="viewmodels:InvoiceViewModel">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="{Binding Total}"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

EDIT

I tried doing this on my ViewModel but it still doesn't return anything

[QueryProperty("Total", "Total")]
    public class InvoiceViewModel : BindableObject
    {
        string _total;
        public string Total
        {

            set
            {
                try
                {

                    _total = Uri.UnescapeDataString(value);
                    OnPropertyChanged();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);

                }

            }
            get { return _total; }

        }
    }

Then on my InvoicePage I have this

[XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class InvoicePage : ContentPage
    {

        public InvoicePage()
        {
            InitializeComponent();
            BindingContext = new InvoiceViewModel();
        }
    }

I don't know if it is because of the route that is faling. Here is my AppShell

 <TabBar Route="main">
        <Tab Route="CategoryPage" Title="Explorar" Icon="tab_feed.png">
            <ShellContent  ContentTemplate="{DataTemplate local:CategoryPage}" />
        </Tab>
        <Tab Route="CartPage" Title="Carrito" Icon="tab_feed.png">
            <ShellContent  ContentTemplate="{DataTemplate local:CartPage}" />
        </Tab>
        <Tab Route="InvoicePage" Title="Factura" Icon="tab_feed.png">
            <ShellContent  ContentTemplate="{DataTemplate local:InvoicePage}" />
        </Tab>
    </TabBar>

And here are the routes I registered

public AppShell()
        {
            InitializeComponent();

            Routing.RegisterRoute(nameof(CategoryPage), typeof(CategoryPage));
            Routing.RegisterRoute(nameof(CartPage), typeof(CartPage));
            Routing.RegisterRoute(nameof(InvoicePage), typeof(InvoicePage));
        }

How can I achieve this? Please help, I don't know what else I can do. Thanks.

Upvotes: 2

Views: 2331

Answers (1)

Jessie Zhang -MSFT
Jessie Zhang -MSFT

Reputation: 13823

The BindingContext is not set at the right time in your code.

When we navigate to page InvoicePage , above code is executed in the following order:

1.the constructor of page InvoicePage

    public InvoicePage()
    {
        InitializeComponent();

        //BindingContext = new InvoiceViewModel(Total);
    }

2.get the passed data from previous page:

    set
        {
            total = Uri.UnescapeDataString(value ?? string.Empty);
            // other code
        }

So, we should set the BindingContext for page InvoicePage after we get the passed data.

You can refer to the following code:

   [XamlCompilation(XamlCompilationOptions.Compile)]
    [QueryProperty("Total", "total")]
    public partial class InvoicePage : ContentPage
    {
        string total;
        public string Total
        {
            set
            {
                total = Uri.UnescapeDataString(value ?? string.Empty);

               // here we can get the passed data and set the `BindingContext` for page `InvoicePage`

                 BindingContext = this;

               // OnPropertyChanged();
            }
            get
            {
                return total;
            }           

        }


        public InvoicePage()
        {
            InitializeComponent();
        }

        // other code

     }

Upvotes: 1

Related Questions