marketally.mopups/README.md
David Friedel d5b0054cb9 Add NuGet package assets and fix license
- Add icon.png for NuGet package
- Add PackageIcon and PackageReadmeFile to csproj
- Fix license from MIT to BSD-3-Clause (correct license per original)
- Add Copyright notice crediting original author

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 22:21:09 +00:00

8.5 KiB

MarketAlly.Mopups

NuGet Version NuGet Downloads License: BSD-3-Clause .NET Platform

Customizable popups for .NET MAUI with multi-window support. A fork of Mopups by Tyson Hooker (LuckyDucko) with enhanced multi-window capabilities for all platforms.

Table of Contents

Features

Core Capabilities (from Mopups)

  • Customizable Popups: Full control over popup appearance and behavior
  • Async/Await Pattern: Modern asynchronous popup handling
  • Animation Support: Built-in appearing and disappearing animations
  • System Padding: Automatic safe area handling
  • Back Button Handling: Customizable back button behavior
  • Cross-Platform: iOS, Android, Windows, and macOS (Mac Catalyst)

New in MarketAlly.Mopups v2.0.0

  • Multi-Window Support: Display popups on specific windows instead of always on the main window
    • Windows: Uses target window's XamlRoot
    • iOS/iPadOS: Uses target window's UIWindowScene
    • macOS Catalyst: Uses target window's UIWindowScene
    • Android: Uses target window's Activity DecorView

Installation

Install via NuGet Package Manager:

dotnet add package MarketAlly.Mopups

Or via Package Manager Console:

Install-Package MarketAlly.Mopups

Quick Start

1. Configure in MauiProgram.cs

using Mopups.Hosting;

public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()
        .ConfigureMopups();  // Add this line

    return builder.Build();
}

2. Create a Popup Page

using Mopups.Pages;

public class MyPopupPage : PopupPage
{
    public MyPopupPage()
    {
        Content = new StackLayout
        {
            Children =
            {
                new Label { Text = "Hello from popup!" },
                new Button { Text = "Close", Command = new Command(async () =>
                    await MopupService.Instance.PopAsync()) }
            }
        };
    }
}

3. Show the Popup

using Mopups.Services;

// Show on main window (default behavior)
await MopupService.Instance.PushAsync(new MyPopupPage());

// Show on specific window (NEW in v2.0.0)
await MopupService.Instance.PushAsync(new MyPopupPage(), targetWindow);

Multi-Window Support

The key enhancement in MarketAlly.Mopups is the ability to display popups on specific windows. This is essential for applications with multiple windows, such as:

  • Helper/tool windows
  • Document windows
  • Settings panels
  • Floating utility windows

API

// Standard push (uses main window)
Task PushAsync(PopupPage page, bool animate = true);

// Window-aware push (NEW)
Task PushAsync(PopupPage page, Window? window, bool animate = true);

Example: Showing Dialog on Helper Window

public class HelperWindow : Window
{
    public async Task ShowConfirmation()
    {
        var popup = new ConfirmationPopup();

        // Pass 'this' to show popup on this window, not the main window
        await MopupService.Instance.PushAsync(popup, this);
    }
}

Platform Implementation Details

Platform How Window is Used
Windows Gets XamlRoot from the target window's native Microsoft.UI.Xaml.Window
iOS/iPadOS Gets UIWindowScene from the target window's native UIWindow
macOS Catalyst Gets UIWindowScene from the target window's native UIWindow
Android Gets DecorView from the target window's Activity

Usage

Basic Popup Operations

// Push a popup
await MopupService.Instance.PushAsync(new MyPopupPage());

// Push with animation control
await MopupService.Instance.PushAsync(new MyPopupPage(), animate: false);

// Pop the topmost popup
await MopupService.Instance.PopAsync();

// Pop all popups
await MopupService.Instance.PopAllAsync();

// Remove specific popup
await MopupService.Instance.RemovePageAsync(specificPopup);

// Check popup stack
var popupStack = MopupService.Instance.PopupStack;

Events

MopupService.Instance.Pushing += (sender, args) =>
    Console.WriteLine($"Pushing: {args.Page}");

MopupService.Instance.Pushed += (sender, args) =>
    Console.WriteLine($"Pushed: {args.Page}");

MopupService.Instance.Popping += (sender, args) =>
    Console.WriteLine($"Popping: {args.Page}");

MopupService.Instance.Popped += (sender, args) =>
    Console.WriteLine($"Popped: {args.Page}");

PopupPage Properties

public class MyPopupPage : PopupPage
{
    public MyPopupPage()
    {
        // Background click dismisses popup
        CloseWhenBackgroundIsClicked = true;

        // Handle safe areas
        HasSystemPadding = true;

        // Background color
        BackgroundColor = Color.FromRgba("#80000000");
    }

    // Override for custom back button behavior
    protected override bool OnBackButtonPressed()
    {
        // Return true to prevent dismissal
        return false;
    }
}

Platform Support

Platform Minimum Version Multi-Window Support
iOS 11.0 Yes (iOS 13+ with UIScene)
Android API 21 (5.0) Yes (Android 7.0+ multi-window)
Windows 10.0.17763.0 Yes
macOS 13.1 (Catalyst) Yes

Requirements

  • .NET 9.0
  • Microsoft.Maui.Controls 9.0+
  • Microsoft.Maui.Essentials 9.0+

License

This project is licensed under the BSD 3-Clause License.

BSD 3-Clause License

Copyright (c) 2022, Tyson Elliot Hooker
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Acknowledgments

This project is a fork of Mopups, originally created by Tyson Hooker (LuckyDucko). We extend our gratitude to:

  • Tyson Hooker - Original author and maintainer of Mopups
  • Maksym Koshovyi - Contributor
  • Aswin P G - Contributor
  • Kirill Lyubimov - Contributor
  • Martijn Van Dijk - Contributor
  • Shane Neuville - Contributor

Mopups itself was created as a replacement for the "Rg.Plugins.Popups" plugin for Xamarin, providing a modern popup solution for .NET MAUI.

Additional Resources


Built with precision by MarketAlly

Multi-window popup support for .NET MAUI applications.