I have a Maui app, with an item collection view and an item detail view.
When an item is tapped in the collection view, I’d like to navigate to the detail view.
I use Maui Shell navigation.
The code comes from a Xamarin app, where it used to work.
The route is registered in AppShell.xaml
In the tap event handler on the collection page code behind
async void OnItemTapped(ItemViewModel itemVM)
{
string route =
$"//{nameof(ItemPage)}?{nameof(ItemPage.Id)}={itemVM.Id}";
await Shell.Current.GoToAsync(route);
}
In debugging, I can verify that the contents of variable route are as expected.
Details page code behind (redacted to relevant bits):
[XamlCompilation(XamlCompilationOptions.Compile)]
[QueryProperty(nameof(Id), nameof(Id))]
public partial class ItemPage : ContentPage, IDisposable
{
/// <summary>Navigation property to pass Id value.</summary>
public string Id { get; set; }
public TablePartyPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
// Id is populated by navigation.
string id = TablePartyId.FromUrlQueryValue(Id); /* Problem: Id is null here */
var viewModel = new ItemViewModel(
...
);
BindingContext = viewModel;
}
}
On executing GotoAsync() the ItemPage constructor, then ItemPage OnAppearing() is executed, however, the navigation property is not populated.
What am I missing?
Environment is:
- Visual Studio 2022, v17.4.3
- Maui v7
2
Answers
It seems like it was a navigation issue, mentioned in this related question: How to register a non-shell-visible navigation route in Maui Shell?
Fixed the non-shell navigation as suggested in the first comment there and navigation property was populated.
Thank you for all your suggestions!
Wow, Maui Navigation doc doesn’t seem to specify when query parameters are applied. It they aren’t applied by the time
OnAppearing
is called, that’s not a good internal design.You could add an issue at
github maui issues
.Work-around is to remove code from
OnAppearing
, put code in property setter(s), to apply property changes. Something like:Seems like a PITA, if there are multiple properties being passed, and all of them need to be set before the "use Id" code runs. In that case, have all setters call a method that does nothing until all properties have expected value.