0

On a MAUI app, I'm trying to pass a value from one page to another through their respective ViewModels, but it's not working and for the life of me I can't figure out why.

Source VM:

[RelayCommand]
public async Task GetAdvertDetailsPageAsync(int advertId)
{
    await Shell.Current.GoToAsync($"{nameof(AdvertDetails)}?AdvertId={advertId.ToString()}");
}

Destination VM:

[QueryProperty("AdvertId", "AdvertId")]

public partial class AdvertDetailsVM : ObservableObject
{
    [ObservableProperty]
    public string advertId;

    public AdvertDetailsVM(IMyHttpClient httpClient)
    {
        LoadAdvertAsync(Convert.ToInt32(AdvertId));
    }

Destination ContentPage:

public partial class AdvertDetails : ContentPage
{
    public AdvertDetails(AdvertDetailsVM vm)
    {

        InitializeComponent();
        BindingContext = vm;
    }
}

The parameter advertId on the GetAdvertDetailsPageAsync on the source page has a value, the destination page gets called, and the ViewModel gets injected just fine, but the AdvertId property on the destination comes up empty and I can't figure out why. For the record, I'm following this tutorial

Thanks in advance

Zidd
  • 164
  • 2
  • 10
  • 2
    you can't assume that the property value has been set when the constructor executes – Jason Nov 30 '22 at 21:56
  • 1
    Move `LoadAdvertAsync` line into AdvertId's setter. To do this, instead of putting `[ObservableProperty]` on advertId, manually write the property. – ToolmakerSteve Nov 30 '22 at 22:10

2 Answers2

0

I figured it out. It's actually working as intended. The problem was that I was checking the property while the constructor was executing, and it turns out it doesn't actually set it until the page finished "navigating to".

So I added this to my destination page:

protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);
    _vm.LoadAdvertAsync();
}

Calling the LoadAdvertAsync() method from here instead, since at this point the property I was trying to pass (AdvertId) has been set and can be worked with (the property is used inside this method and is not a parameter of it anymore).

Zidd
  • 164
  • 2
  • 10
0

The way you want to deal with your problem is this:

public partial class AdvertDetailsVM : ObservableObject, IQueryAttributable

You implement method of that interface, that executes when you get your query:

public void ApplyQueryAttributes(IDictionary<string, object> query)

Inside this method you access your data, using this:

AdvertId = query["AdvertId"] as string;
H.A.H.
  • 2,104
  • 1
  • 8
  • 21