How to load data from parameter on MAUI page load

69 Views Asked by At

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.

1

There are 1 best solutions below

0
Jianwei Sun - MSFT On

Inheriting HabitModel from ObservableObject should also solve the problem:

public class HabitModel : ObservableObject
{
    //properties
}

You can check my answer of this case: Maui App - Page is not updating observable property.