- Article
Popups are a very common way of presenting information to a user that relates to their current task. Operating systems provide a way to show a message and require a response from the user, these alerts are typically restrictive in terms of the content a developer can provide and also the layout and appearance.
Note
If you wish to present something to the user that is more subtle then checkout our Toast and Snackbar options.
The Popup
view allows developers to build their own custom UI and present it to their users.
Building a Popup
A Popup
can be created in XAML or C#:
XAML
Including the XAML namespace
In order to use the toolkit in XAML the following xmlns
needs to be added into your page or view:
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
Therefore the following:
<ContentPage x:Class="CommunityToolkit.Maui.Sample.Pages.MyPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"></ContentPage>
Would be modified to include the xmlns
as follows:
<ContentPage x:Class="CommunityToolkit.Maui.Sample.Pages.MyPage" 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"></ContentPage>
Defining your Popup
Please note that if a Popup
is created in XAML it must have a C# code behind file as well. To understand why this is required please refer to this .NET MAUI documentation page.
The easiest way to create a Popup
is to add a new .NET MAUI ContentView (XAML)
to your project and then change each of the files to the following:
<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"> <VerticalStackLayout> <Label Text="This is a very important message!" /> </VerticalStackLayout> </toolkit:Popup>
public partial class SimplePopup : Popup{ public SimplePopup() { InitializeComponent(); }}
Important
If the code behind file is not created along with the call to InitializeComponent
then an exception will be thrown when trying to display your Popup
.
C#
using CommunityToolkit.Maui.Views;var popup = new Popup{ Content = new VerticalStackLayout { Children = { new Label { Text = "This is a very important message!" } } }};
Presenting a Popup
Once the Popup
has been built it can then be presented through the use of our Popup
extension methods or through the IPopupService
implementation from this toolkit.
IPopupService
The .NET MAUI Community Toolkit provides a mechanism to instantiate and present popups in a .NET MAUI application. The popup service is automatically registered with the MauiAppBuilder
when using the UseMauiCommunityToolkit
initialization method. This enables you to resolve an IPopupService
implementation in any part of your application.
The IPopupService
makes it possible to register a popup view and its associated view model. The ability to show a Popup
can now be driven by only providing the view model making it possible to keep a clean separation between view and view model.
Registering Popups
In order to first use the IPopupService
to display a popup in your application you will need to register the popup and view model with the MauiAppBuilder
, this can be done through the use of Register Popup View and View Model.
Displaying Popups
The following example shows how to use the IPopupService
to create and display a popup in a .NET MAUI application:
public class MyViewModel : INotifyPropertyChanged{ private readonly IPopupService popupService; public MyViewModel(IPopupService popupService) { this.popupService = popupService; } public void DisplayPopup() { this.popupService.ShowPopup<UpdatingPopupViewModel>(); }}
For a more concrete example please refer to our sample application and the example in MultiplePopupViewModel
The IPopupService
also provides methods to handle a result being returned from a Popup as covered in Returning a result.
Passing data to a Popup view model
When presenting a Popup we sometimes need to pass data across to the underlying view model to allow for dynamic content to be presented to the user. The IPopupService
makes this possible through the overloads of the ShowPopup
and ShowPopupAsync
methods that takes a Action<TViewModel> onPresenting
parameter. This parameter has been designed to be framework agnostic and allow you as a developer to drive the loading/passing of data however best fits your architecture.
To extend the previous example of showing a UpdatingPopupViewModel
and its associated Popup, we can use the onPresenting
parameter to pass in the number of updates that we wish to perform:
public class MyViewModel : INotifyPropertyChanged{ private readonly IPopupService popupService; public MyViewModel(IPopupService popupService) { this.popupService = popupService; } public void DisplayPopup() { this.popupService.ShowPopup<UpdatingPopupViewModel>(onPresenting: viewModel => viewModel.PerformUpdates(10)); }}
Extension methods
Important
A Popup
can only be displayed from a Page
or an implementation inheriting from Page
.
using CommunityToolkit.Maui.Views;public class MyPage : ContentPage{ public void DisplayPopup() { var popup = new SimplePopup(); this.ShowPopup(popup); }}
Closing a Popup
There are 2 different ways that a Popup
can be closed; programmatically or by tapping outside of the popup.
Programmatically closing a Popup
In order to close a Popup
a developer must call Close
or CloseAsync
on the Popup
itself. This is typically performed by responding to a button press from a user.
We can enhance the previous XAML example by adding an OK Button
:
<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"> <VerticalStackLayout> <Label Text="This is a very important message!" /> <Button Text="OK" Clicked="OnOKButtonClicked" /> </VerticalStackLayout> </toolkit:Popup>
In the resulting event handler we call Close
, this will programmatically close the Popup
.
Note
Close()
is a fire-and-forget method. It will complete and return to the calling thread before the operating system has dismissed the Popup
from the screen. If you need to pause the execution of your code until the operating system has dismissed the Popup
from the screen, use instead CloseAsync()
.
public partial class MySimplePopup : Popup{ // ... void OnOKButtonClicked(object? sender, EventArgs e) => Close();}
In the resulting event handler we call CloseAsync
, this will programmatically close the Popup
allowing the caller to await
the method until the operating system has dismissed the Popup
from the screen.
public partial class MySimplePopup : Popup{ // ... async void OnOKButtonClicked(object? sender, EventArgs e) { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); await CloseAsync(token: cts.Token); await Toast.Make("Popup Dismissed By Button").Show(); }}
Tapping outside of the Popup
By default a user can tap outside of the Popup
to dismiss it. This can be controlled through the use of the CanBeDismissedByTappingOutsideOfPopup
property. Setting this property to false
will prevent a user from being able to dismiss the Popup
by tapping outside of it.
Returning a result
A developer will quite often seek a response from their user, the Popup
view allows developers to return a result that can be awaited for and acted on.
We can enhance our original XAML example to show how this can be accomplished:
XAML
By adding 2 new buttons to the XAML:
<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"> <VerticalStackLayout> <Label Text="This is a very important message! Do you agree?" /> <Button Text="Yes" Clicked="OnYesButtonClicked" /> <Button Text="No" Clicked="OnNoButtonClicked" /> </VerticalStackLayout> </toolkit:Popup>
Then adding the following event handlers in the C#:
async void OnYesButtonClicked(object? sender, EventArgs e){ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); await CloseAsync(true, cts.Token);}async void OnNoButtonClicked(object? sender, EventArgs e){ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); await CloseAsync(false, cts.Token);}
The Close
method allows for an object
value to be supplied, this will be the resulting return value. In order to await the result the ShowPopupAsync
method must be used as follows:
using CommunityToolkit.Maui.Views;public class MyPage : ContentPage{ public async Task DisplayPopup() { var popup = new SimplePopup(); var result = await this.ShowPopupAsync(popup, CancellationToken.None); if (result is bool boolResult) { if (boolResult) { // Yes was tapped } else { // No was tapped } } }}
Note
In order to handle the tapping outside of a Popup
when also awaiting the result you can change the value that is returned through the ResultWhenUserTapsOutsideOfPopup
property.
Styling
The Popup
class allows the use of .NET MAUI Styles to make it easier to share common visual settings across multiple popups.
The following example shows how to define a style that applies to the SimplePopup
example from the previous section.
<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" xmlns:popups="clr-namespace:CommunityToolkit.Maui.Sample.Views.Popups" x:Class="MyProject.SimplePopup"> <toolkit:Popup.Resources> <Style TargetType="{x:Type popups:SimplePopup}"> <Setter Property="Size" Value="100,200" /> <Setter Property="Color" Value="Green" /> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="VerticalOptions" Value="Start" /> <Setter Property="CanBeDismissedByTappingOutsideOfPopup" Value="True" /> </Style> </toolkit:Popup.Resources> <VerticalStackLayout> <Label Text="This is a very important message! Do you agree?" /> <Button Text="Yes" Clicked="OnYesButtonClicked" /> <Button Text="No" Clicked="OnNoButtonClicked" /> </VerticalStackLayout> </toolkit:Popup>
Note
When creating a Style
that targets Popup
and you wish to make it apply to custom popups like the SimplePopup
example, make sure to set the ApplyToDerivedTypes property on the Style
definition.
Properties
Property | Type | Description |
---|---|---|
Anchor | View | Gets or sets the View anchor. The Anchor is where the Popup will render closest to. When an Anchor is configured the popup will appear centered over that control or as close as possible. |
CanBeDismissedByTappingOutsideOfPopup | bool | Gets or sets a value indicating whether the popup can be dismissed by tapping outside of the Popup. On Android - when false the hardware back button is disabled. |
Color | Color | Gets or sets the Color of the Popup. This color sets the native background color of the Popup , which is independent of any background color configured in the actual Content . |
Content | View | Gets or sets the View content to render in the Popup . |
HorizontalOptions | LayoutAlignment | Gets or sets the LayoutAlignment for positioning the Popup horizontally on the screen. |
Result | Task<object?> | Gets the final result of the dismissed Popup . |
Size | Size | Gets or sets the Size of the Popup Display. The Popup will always try to constrain the actual size of the Popup to the size of the View unless a Size is specified. If the Popup uses the HorizontalOptions or VerticalOptions properties that are not the defaults then this Size property is required. |
VerticalOptions | LayoutAlignment | Gets or sets the LayoutAlignment for positioning the Popup vertically on the screen. |
Events
Event | Description |
---|---|
Closed | Occurs when the Popup is closed. |
Opened | Occurs when the Popup is opened. |
Examples
You can find an example of this feature in action in the .NET MAUI Community Toolkit Sample Application.
API
You can find the source code for Popup
over on the .NET MAUI Community Toolkit GitHub repository.