[BUG] ViewModel that gets passed to PopupService gets ignored
Is there an existing issue for this?
- [X] I have searched the existing issues
Did you read the "Reporting a bug" section on Contributing file?
- [X] I have read the "Reporting a bug" section on Contributing file: https://github.com/CommunityToolkit/Maui/blob/main/CONTRIBUTING.md#reporting-a-bug
Current Behavior
Popupservice allows you to pass an existing ViewModel, and it will get the correct popup. It does get the correct popup, but the viewmodel you pass through gets ignored, a new (empty) one gets made that makes it into the popup.
https://github.com/CommunityToolkit/Maui/blob/819ab10a3a53c76e514410e8ee0af2c5c7a6fe9c/src/CommunityToolkit.Maui/PopupService.cs#L115-L124 The variable doesn't seem to be getting used.
Expected Behavior
ViewModel should be passed to the Popup instance and be the current active BindingContext
Steps To Reproduce
Implement the PopupService according to https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/views/popup Then try the overload where you can pass your existing ViewModel to create a Popup.
I've added a link to an example repro that implements the popups in the same way I did, except it doesn't use the overload anywhere.
Link to public reproduction project repository
https://github.com/jfversluis/MauiToolkitPopupSample
Environment
- .NET MAUI CommunityToolkit: 9.0.1
- OS: Android 34
- .NET MAUI: 8.0.60
Anything else?
I hope this fixes my popups not scaling to content. Knock on wood.
Why do you need to use this overload instead of the onPresenting overload? The functionality that you are after was removed before the popup service got merged and there is a current expectation that we will remove the method entirely
Because we're already managing our ViewModel. I can start syncing variables in the onPresenting on the newly created one, but that's less than ideal.
The overload seemed plenty, and well fit for our need. I used it because it was there.
Yeah I get that and you are not the first to ask this. Also I've noticed that our XML docs state the behaviour you are expecting should be the case. Let me see what the rest of the team think
Maybe I am not understanding the issue. This worked for me:
var vm = new LocationViewModel(_locationdatastore); await vm.Refresh(); var popup = new PopupLocationsView(vm); var result = await Shell.Current.ShowPopupAsync(popup, CancellationToken.None);
Maybe I am not understanding the issue. This worked for me:
var vm = new LocationViewModel(_locationdatastore); await vm.Refresh(); var popup = new PopupLocationsView(vm); var result = await Shell.Current.ShowPopupAsync(popup, CancellationToken.None);
~~The code won't error and a popup will show, however anything you filled into the viewmodel will be ignored, as your vm instance isn't the one used in the actual popup~~
See response below, the code in quoted post is different code than discussed in initial ticket.
The vm did work. My popup is using binding to an ObservableCollection in the vm. Everything is displayed as defined in the vm. It works great. I use this popup to permit the user to delete entries stored in a database.
Oh, I'm sorry, I see where I went wrong in my response.
This ticket relates to the CommunityToolkit.Maui.Core.PopupService class. https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/views/popup#displaying-popups
Specifically, its exposed method ShowPopupAsync() as linked in the main post.
The Shell method works fine because you create your own view, whereas the PopupService handles this itself.
Facing the same issue on my side!
From what I'm seeing so far, the easiest fix would be to create another GetPopup method taking the ViewModel as a parameter and setting it as BindingContext like so:
Popup GetPopup<TViewModel>(
TViewModel viewModel)
{
var popup = GetPopup(
typeof(TViewModel));
popup.BindingContext = viewModel;
return popup;
}
In the ShowPopup methods that request a ViewModel as parameter, it would then be necessary to call this new GetPopup method.
We will be deprecating the public void ShowPopup<TViewModel>(TViewModel) API. It will be marked [Obsolete] in the next release.
I understand the desire, and we've discussed the pros + cons of this in the past in our monthly standups.
However, it's wrong for an API called ShowPopup to do any hidden variable assignment under the hood that the caller may be unaware of. It is also a breaking change because it breaks existing functionality for folks currently using the API as designed.
The recommended way to use PopupService is to add both the Popup and its ViewModel to builder.Services using PopupService.AddTransient in MauiProgram.cs, then call PopupService.ShowPopup<TViewModel>().