Skip to content

Migrating to Popup v2

Shaun Lawrence edited this page May 19, 2025 · 12 revisions

We recently shipped version 2 of the Popup in the .NET MAUI Community Toolkit.

This comes with a number of breaking changes but we promise that you are going to love the result!

Why did we break things?

We did try hard to make a seamless migration path however this was just not feasible. We experienced an overwhelming number of issues in the original popup implementation and made the hard decision to drop and replace it with something we believe will be much more stable.

The original implementation made use of platform specific implementations to show the popup (e.g. UIPopoverPresentationController on iOS and macOS) while this worked well at the general presentation of a view it lead to many issues within our codebase aimed at dealing with layouts and sizing of the content - this is something that MAUI already does for us.

The sheer fact that the Pull Request introducing popup v2 closed 31 issues just goes to show the impact!

Migrating from v1 to v2

If you are in the process of migrating from v1 to v2 or are about to begin that journey the following article is aimed at helping.

The IPopupService interface has moved namespaces

We have moved IPopupService from CommunityToolkit.Maui.Core to CommunityToolkit.Maui. You will likely need to update any using statements in the files where you use IPopupService from using CommunityToolkit.Maui.Core; to using CommunityToolkit.Maui;.

Enabled support for showing the same popup instance multiple times

Yes we understand that this was a rather limited factor with the old implementation, thankfully the new approach makes it possible to show the same instance multiple times. This improvement was the influence behind the next improvement:

Introduced AddSingletonPopup and AddScopedPopup

Now that popups can be displayed multiple times we have provided support for registering popups as singleton or scoped services.

Removed the need to subclass Popup

You can now use any View as the popup content without inheriting from Popup. The only caveat to this rule is - if you need to return a result from the popup, you have to inherit from Popup.

Replaced properties

Popup now inherits from ContentView which provides similar properties to what had been added to the original Popup implementation. In order to provide a much more consistent approach with how developers build their user interfaces we took the decision to shift over to the using the properties that come out of the box from .NET MAUI, therefore the following has been modified:

Size is replaced with WidthRequest and HeightRequest

<toolkit:Popup 
    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"
    x:Class="MyProject.SimplePopup"
-   Size="100,200"
+   WidthRequest="100"
+   HeightRequest="200">
    
</toolkit:Popup>

Color is replaced with BackgroundColor

<toolkit:Popup 
    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"
    x:Class="MyProject.SimplePopup"
-   Color="Green"
+   BackgroundColor="Green">
    
</toolkit:Popup>

CanBeDismissedByTappingOutsideOfPopup has been moved

This can now be controller by the PopupOptions class.

Improved styling out of the box

Popups now have their content wrapped inside a Border control making it easy to style without having to increase the complexity of your popup view.

This can now be controller by the PopupOptions class.

PopupOptions

When displaying a popup through the IPopupService, Page, Shell or INavigation, developers can now pass in options that customize the behavior and appearance of the displayed popup.

CanBeDismissedByTappingOutsideOfPopup

PageOverlayColor

OnTappingOutsideOfPopup

Shape

Shadow

Passing data to a popup has changed

The original way of passing data through the onPresenting parameter when calling IPopupService.Show no longer exists. This has now been replaced by using the IQueryAttributable interface that integrates with .NET MAUI Shell. You can use it just like you do with .NET MAUI Shell to Process navigation data using a single method. This change was made in order to provide a unified and therefore consistent way of passing navigation data around a .NET MAUI application.

Original way:

public class NamePopupViewModel : ObservableObject
{
    [ObservableProperty]
    string name = "";
}

public class MyViewModel : INotifyPropertyChanged
{
    private readonly IPopupService popupService;

    public MyViewModel(IPopupService popupService)
    {
        this.popupService = popupService;
    }

    public void DisplayPopup()
    {
        this.popupService.ShowPopup<NamePopupViewModel>(onPresenting: viewModel => viewModel.Name = "Shaun");
    }
}

New way:

public class NamePopupViewModel : ObservableObject, IQueryAttributable
{
    [ObservableProperty]
    string name = "";

    public void ApplyQueryAttributes(IDictionary<string, object> query)
    {
        Name = query["Name"] as string;
    }
}

public class MyViewModel : INotifyPropertyChanged
{
    private readonly IPopupService popupService;

    public MyViewModel(IPopupService popupService)
    {
        this.popupService = popupService;
    }

    public async Task DisplayPopup()
    {
        var queryAttributes = new Dictionary<string, object>
        {
            ["Name"] = "Shaun"
        };

        await this.popupService.ShowPopupAsync<NamePopupViewModel>(
            Shell.Current,
            options: null,
            queryAttributes);
    }
}

IPopupService.Show methods

MAUI Community Toolkit

About

Usage

Migration Guides

Contribution

Development/Testing

Monthly Standups

Core Maintainers

Clone this wiki locally