I am navigating to a page and would like to load an object from an ID. Currently this is just "loaded" from a list, but in future will be from a database.
This is the query passing code from page 1:
await Shell.Current.GoToAsync($"{nameof(HabitPage)}?Id={_Habit.id}");
Which is received by the following view and associated view model:
public partial class HabitPage : ContentPage
{
public HabitPage(HabitViewModel habitViewModel)
{
InitializeComponent();
BindingContext = habitViewModel;
}
}
[QueryProperty("Id", "Id")]
public partial class HabitViewModel : ObservableObject
{
[ObservableProperty]
private int id;
...
}
This part works - I can bind a component to this and get the correct ID to display on the page, however that setting of the Id property behind id occurs after the constructor, etc. so I am struggling to call a method which loads the full object from the "database".
I found a few posts like this one which suggest using the OnAppearing method to trigger the loading of the object, however I have tried to implement that in the page code-behind and in the view model as follows and am still having no luck:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:viewModels="clr-namespace:HabitTracker.ViewModels"
x:DataType="viewModels:HabitViewModel"
x:Class="HabitTracker.Views.HabitPage"
Title="Habit"
Padding="10">
<ContentPage.Behaviors>
<toolkit:EventToCommandBehavior
Command="{Binding AppearingCommand}"
EventName="Appearing" />
</ContentPage.Behaviors>
<VerticalStackLayout>
<Label
Text="{Binding Habit.Name}" <!-- This is blank -->
Style="{StaticResource habitTitle}" />
<Label Text="{Binding Id}" /> <!-- This shows up correctly -->
</VerticalStackLayout>
</ContentPage>
[QueryProperty("Id", "Id")]
public partial class HabitViewModel : ObservableObject
{
[ObservableProperty]
private int id;
public HabitModel Habit { get; private set; }
[RelayCommand]
private void Appearing()
{
Habit = HabitRepository.GetHabitById(Id);
}
}
The method gets called, the correct object is loaded and assigned to Habit, but the page never displays the updated value of name.
If I manually assign a value to Habit, e.g.:
public HabitModel Habit { get; private set; } = new() { Name = "Test" };
"Test" shows up on the page and is not replaced by the value of the loaded object.
Inheriting HabitModel from
ObservableObjectshould also solve the problem:You can check my answer of this case: Maui App - Page is not updating observable property.