.NET MAUI query parameter and community toolkit issue

171 views Asked by At

I tried to pass an object parameter thru ViewModel Books to ViewModel Book Detail. I defined both viewmodels as ObservableObject and used a dictionary in ViewModel Books to pass parateter like below:

I expect to have Title = this.Book.Name; to work and get the value, but the this. Book or even Book property alone is null, but I can get its value in Details XAML page. I need it on the DetailsViewModel constructor. What's my issue?

BooksViewModel.cs

[RelayCommand]
async Task GoToDestinationAsync(Book book)
{
    await Shell.Current.GoToAsync($"{nameof(DetailsPage)}", true,
    new Dictionary<string, object>
    {
        {"Book",book}
    });
}

DetailsViewModel.cs

[QueryProperty(nameof(Book), "Book")]
public partial class BookDetailsViewModel : BaseViewModel
{
    [ObservableProperty]
    Book book;

    public BookDetailsViewModel()
    {
        Title = this.Book.Name;
    }
}

DetailsPage.xaml.cs

public partial class DetailsPage : ContentPage
{
    public DetailsPage(MonkeyDetailsViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }

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

AppShell.cs

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();

        Routing.RegisterRoute(nameof(DetailsPage), typeof(DetailsPage));
    }
}

MauiProgram.cs

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        
        builder.Services.AddSingleton<BooksViewModel>();
        builder.Services.AddTransient<BookDetailsViewModel>();

        builder.Services.AddSingleton<MainPage>();
        builder.Services.AddTransient<DetailsPage>();


        return builder. Build();
    }
}
1

There are 1 answers

0
Liqun Shen-MSFT On

As Jason said, constructor runs first so you cannot get the Book property. I assume that you may want to set the initial value for Title property. But I think you don't have to set the value in constructor. You could just set the value in Setter method:

    Book book;
    public Book Book
    {
        ...
        set
        {
            book = value;
            Title = book.Name;
        }                      
    }

    [ObservableProperty]
    string title;

Also, in MAUI page has OnAppearing method, you could also set the value in OnAppearing method in code behind.

protected override void OnAppearing()
{
    base.OnAppearing();
    //get the value from viewmodel and set the value

}

For more info, you may refer to Pass data

Hope it helps!