Closed
Add IAlertManager interface to enable custom AlertManager implementations#33267
Conversation
Copilot
AI
changed the title
[WIP] Create IAlertManager interface for AlertManager behavior replacement
Add IAlertManager interface to enable custom AlertManager implementations
Dec 22, 2025
This was referenced Dec 23, 2025
Member
|
/rebase |
…ions - Create internal IAlertManager interface with TODO to make public in NET11 - Make AlertManager implement IAlertManager - Update Window to retrieve IAlertManager from services with fallback to default - Update tests to cast to concrete AlertManager when checking internal state - Add test to verify custom IAlertManager can be provided via services Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
The MockServiceProvider was throwing KeyNotFoundException when a service wasn't registered, but IServiceProvider.GetService should return null. This broke tests that relied on service resolution fallback behavior. Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
github-actions
Bot
force-pushed
the
copilot/create-ialertmanager-interface
branch
from
January 29, 2026 21:15
68b02ab to
c85cc8d
Compare
kubaflo
pushed a commit
that referenced
this pull request
Apr 4, 2026
…4228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: #33267 (draft, creates internal `IAlertManager` for #33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
PureWeen
pushed a commit
that referenced
this pull request
Apr 8, 2026
…4228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: #33267 (draft, creates internal `IAlertManager` for #33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
devanathan-vaithiyanathan
pushed a commit
to devanathan-vaithiyanathan/maui
that referenced
this pull request
Apr 9, 2026
…tnet#34228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes dotnet#34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: dotnet#33267 (draft, creates internal `IAlertManager` for dotnet#33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
PureWeen
pushed a commit
that referenced
this pull request
Apr 14, 2026
…4228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: #33267 (draft, creates internal `IAlertManager` for #33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
devanathan-vaithiyanathan
pushed a commit
to Tamilarasan-Paranthaman/maui
that referenced
this pull request
Apr 21, 2026
…tnet#34228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes dotnet#34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: dotnet#33267 (draft, creates internal `IAlertManager` for dotnet#33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
Ahamed-Ali
pushed a commit
that referenced
this pull request
Apr 22, 2026
…4228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: #33267 (draft, creates internal `IAlertManager` for #33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
PureWeen
pushed a commit
that referenced
this pull request
Apr 22, 2026
…4228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: #33267 (draft, creates internal `IAlertManager` for #33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
PureWeen
pushed a commit
that referenced
this pull request
Apr 28, 2026
…4228) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #34104 Custom platform backends (e.g., Linux/GTK) currently have no supported way to implement `DisplayAlert()`, `DisplayActionSheet()`, or `DisplayPromptAsync()`. The entire alert pipeline (`AlertManager`, `IAlertManagerSubscription`) is internal, forcing custom backends to use `DispatchProxy` + heavy reflection to intercept dialog requests. This PR introduces two public interfaces to enable custom platform backends to implement alert dialogs without reflection: ### New Public APIs **`IAlertManager`** — Public interface for the full alert management lifecycle. Custom backends can implement this to completely replace the default `AlertManager`: ```csharp public interface IAlertManager { void Subscribe(); void Unsubscribe(); void RequestAlert(Page page, AlertArguments arguments); void RequestActionSheet(Page page, ActionSheetArguments arguments); void RequestPrompt(Page page, PromptArguments arguments); } ``` **`IAlertManagerSubscription`** — Public interface for platform-specific dialog implementations. The default `AlertManager` already resolves this from DI, so custom backends can register their implementation directly: ```csharp public interface IAlertManagerSubscription { void OnAlertRequested(Page sender, AlertArguments arguments); void OnActionSheetRequested(Page sender, ActionSheetArguments arguments); void OnPromptRequested(Page sender, PromptArguments arguments); } ``` ### Usage Two levels of customization are now available: ```csharp // Simple: Just provide custom dialog implementations builder.Services.AddSingleton<IAlertManagerSubscription, GtkAlertSubscription>(); // Advanced: Replace the entire alert management system builder.Services.AddSingleton<IAlertManager, CustomAlertManager>(); ``` ### Changes - **New:** `IAlertManager` public interface in `Microsoft.Maui.Controls.Platform` - **New:** `IAlertManagerSubscription` public interface (moved from internal nested interface) - **Modified:** `AlertManager` now implements `IAlertManager` - **Modified:** `Window.AlertManager` property typed as `IAlertManager`, resolves custom implementation from DI - **Modified:** Tests updated + 2 new tests for DI resolution - **Updated:** All `PublicAPI.Unshipped.txt` files ### Related - Related PR: #33267 (draft, creates internal `IAlertManager` for #33266) - Real-world use case: [Maui.Gtk GtkAlertManager](https://github.com/redth/Maui.Gtk/blob/main/src/Platform.Maui.Linux.Gtk4/Platform/GtkAlertManager.cs) — 370 lines of reflection that this PR eliminates ---------
kubaflo
added a commit
that referenced
this pull request
Apr 30, 2026
…PI changes) (#35095) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Enables third-party platform backends (for example Maui.Gtk) to provide their own `DisplayAlertAsync` / `DisplayActionSheetAsync` / `DisplayPromptAsync` implementations without MAUI exposing any new public API. This complements #33267: because that PR introduces a new public interface, it must wait for .NET 11. This PR solves the same problem using already-shipped public argument types, so it is shippable in .NET 10. `AlertManager.Subscribe()` now keeps the existing explicit internal `IAlertManagerSubscription` path, then checks for keyed delegate registrations before falling back to the platform default. The delegate signatures use only existing public types: ```csharp Func<Page, AlertArguments, Task<bool>> Func<Page, ActionSheetArguments, Task<string>> Func<Page, PromptArguments, Task<string>> ``` The registrations are keyed so MAUI does not accidentally consume unrelated `Func<>` services: | Dialog | Service key | |---|---| | Alert | `Microsoft.Maui.Controls.DisplayAlert` | | Action sheet | `Microsoft.Maui.Controls.DisplayActionSheet` | | Prompt | `Microsoft.Maui.Controls.DisplayPrompt` | Consumer usage: ```csharp builder.Services.AddKeyedSingleton<Func<Page, AlertArguments, Task<bool>>>( "Microsoft.Maui.Controls.DisplayAlert", async (page, args) => { return await MyGtkDialog.ShowAsync(args.Title, args.Message, args.Accept, args.Cancel); }); ``` If any keyed delegate is registered, MAUI wraps it in a new internal `DelegateAlertSubscription`. Registered operations dispatch to their delegate; unregistered operations fall through to the platform default. The delegate returns the dialog result and MAUI completes the corresponding `AlertArguments`, `ActionSheetArguments`, or `PromptArguments` internally. If the delegate returns `null`, faults, or cancels, the caller observes that through the original `Display*Async` task instead of hanging silently. Precedence order in `Subscribe()`: 1. Explicit `IAlertManagerSubscription` service (existing internal path, unchanged) 2. Keyed result-returning delegate convention (new) 3. Platform default subscription (existing fallback) ### Notes for reviewers - Zero public API surface: no `PublicAPI.*.txt` changes. The new `DelegateAlertSubscription` class and key constants are internal; consumers use literal string keys documented on the existing argument types. - Keyed registrations are intentional. Unkeyed `Func<>` services are ignored to avoid accidental collisions. - The delegate returns the dialog result instead of calling `args.SetResult(...)`. This matches the built-in async platform pattern where MAUI completes the argument after awaiting the native dialog result. - Per-operation fall-through is intentional. A backend can override just alerts and keep the platform action sheet/prompt, for example. - `OnPageBusy` is excluded from the convention (obsolete in .NET 10, removed in .NET 11) and always routes to the fallback. - When .NET 11 ships a proper public `IAlertManager`/`IAlertDialogProvider`, this delegate convention can stay as a lightweight alias or be deprecated. Either way, .NET 10 consumers are unblocked now. ### Tests Unit coverage in `AlertManagerTests.cs` includes: - Alert, action sheet, and prompt delegate dispatch - Returned delegate results completing the original `Display*Async` caller - Unregistered operation fall-through - Unkeyed delegate services being ignored - Explicit `IAlertManagerSubscription` precedence - Synchronous and asynchronous delegate faults - Delegate cancellation forwarding - Null task contract violation Focused `AlertManagerTests` pass locally: 21/21. ### Issues Fixed Fixes #34104 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
github-actions Bot
pushed a commit
that referenced
this pull request
May 6, 2026
…PI changes) (#35095) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Enables third-party platform backends (for example Maui.Gtk) to provide their own `DisplayAlertAsync` / `DisplayActionSheetAsync` / `DisplayPromptAsync` implementations without MAUI exposing any new public API. This complements #33267: because that PR introduces a new public interface, it must wait for .NET 11. This PR solves the same problem using already-shipped public argument types, so it is shippable in .NET 10. `AlertManager.Subscribe()` now keeps the existing explicit internal `IAlertManagerSubscription` path, then checks for keyed delegate registrations before falling back to the platform default. The delegate signatures use only existing public types: ```csharp Func<Page, AlertArguments, Task<bool>> Func<Page, ActionSheetArguments, Task<string>> Func<Page, PromptArguments, Task<string>> ``` The registrations are keyed so MAUI does not accidentally consume unrelated `Func<>` services: | Dialog | Service key | |---|---| | Alert | `Microsoft.Maui.Controls.DisplayAlert` | | Action sheet | `Microsoft.Maui.Controls.DisplayActionSheet` | | Prompt | `Microsoft.Maui.Controls.DisplayPrompt` | Consumer usage: ```csharp builder.Services.AddKeyedSingleton<Func<Page, AlertArguments, Task<bool>>>( "Microsoft.Maui.Controls.DisplayAlert", async (page, args) => { return await MyGtkDialog.ShowAsync(args.Title, args.Message, args.Accept, args.Cancel); }); ``` If any keyed delegate is registered, MAUI wraps it in a new internal `DelegateAlertSubscription`. Registered operations dispatch to their delegate; unregistered operations fall through to the platform default. The delegate returns the dialog result and MAUI completes the corresponding `AlertArguments`, `ActionSheetArguments`, or `PromptArguments` internally. If the delegate returns `null`, faults, or cancels, the caller observes that through the original `Display*Async` task instead of hanging silently. Precedence order in `Subscribe()`: 1. Explicit `IAlertManagerSubscription` service (existing internal path, unchanged) 2. Keyed result-returning delegate convention (new) 3. Platform default subscription (existing fallback) ### Notes for reviewers - Zero public API surface: no `PublicAPI.*.txt` changes. The new `DelegateAlertSubscription` class and key constants are internal; consumers use literal string keys documented on the existing argument types. - Keyed registrations are intentional. Unkeyed `Func<>` services are ignored to avoid accidental collisions. - The delegate returns the dialog result instead of calling `args.SetResult(...)`. This matches the built-in async platform pattern where MAUI completes the argument after awaiting the native dialog result. - Per-operation fall-through is intentional. A backend can override just alerts and keep the platform action sheet/prompt, for example. - `OnPageBusy` is excluded from the convention (obsolete in .NET 10, removed in .NET 11) and always routes to the fallback. - When .NET 11 ships a proper public `IAlertManager`/`IAlertDialogProvider`, this delegate convention can stay as a lightweight alias or be deprecated. Either way, .NET 10 consumers are unblocked now. ### Tests Unit coverage in `AlertManagerTests.cs` includes: - Alert, action sheet, and prompt delegate dispatch - Returned delegate results completing the original `Display*Async` caller - Unregistered operation fall-through - Unkeyed delegate services being ignored - Explicit `IAlertManagerSubscription` precedence - Synchronous and asynchronous delegate faults - Delegate cancellation forwarding - Null task contract violation Focused `AlertManagerTests` pass locally: 21/21. ### Issues Fixed Fixes #34104 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
Collaborator
|
Done here #34228 |
PureWeen
pushed a commit
that referenced
this pull request
Jun 2, 2026
…PI changes) (#35095) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Enables third-party platform backends (for example Maui.Gtk) to provide their own `DisplayAlertAsync` / `DisplayActionSheetAsync` / `DisplayPromptAsync` implementations without MAUI exposing any new public API. This complements #33267: because that PR introduces a new public interface, it must wait for .NET 11. This PR solves the same problem using already-shipped public argument types, so it is shippable in .NET 10. `AlertManager.Subscribe()` now keeps the existing explicit internal `IAlertManagerSubscription` path, then checks for keyed delegate registrations before falling back to the platform default. The delegate signatures use only existing public types: ```csharp Func<Page, AlertArguments, Task<bool>> Func<Page, ActionSheetArguments, Task<string>> Func<Page, PromptArguments, Task<string>> ``` The registrations are keyed so MAUI does not accidentally consume unrelated `Func<>` services: | Dialog | Service key | |---|---| | Alert | `Microsoft.Maui.Controls.DisplayAlert` | | Action sheet | `Microsoft.Maui.Controls.DisplayActionSheet` | | Prompt | `Microsoft.Maui.Controls.DisplayPrompt` | Consumer usage: ```csharp builder.Services.AddKeyedSingleton<Func<Page, AlertArguments, Task<bool>>>( "Microsoft.Maui.Controls.DisplayAlert", async (page, args) => { return await MyGtkDialog.ShowAsync(args.Title, args.Message, args.Accept, args.Cancel); }); ``` If any keyed delegate is registered, MAUI wraps it in a new internal `DelegateAlertSubscription`. Registered operations dispatch to their delegate; unregistered operations fall through to the platform default. The delegate returns the dialog result and MAUI completes the corresponding `AlertArguments`, `ActionSheetArguments`, or `PromptArguments` internally. If the delegate returns `null`, faults, or cancels, the caller observes that through the original `Display*Async` task instead of hanging silently. Precedence order in `Subscribe()`: 1. Explicit `IAlertManagerSubscription` service (existing internal path, unchanged) 2. Keyed result-returning delegate convention (new) 3. Platform default subscription (existing fallback) ### Notes for reviewers - Zero public API surface: no `PublicAPI.*.txt` changes. The new `DelegateAlertSubscription` class and key constants are internal; consumers use literal string keys documented on the existing argument types. - Keyed registrations are intentional. Unkeyed `Func<>` services are ignored to avoid accidental collisions. - The delegate returns the dialog result instead of calling `args.SetResult(...)`. This matches the built-in async platform pattern where MAUI completes the argument after awaiting the native dialog result. - Per-operation fall-through is intentional. A backend can override just alerts and keep the platform action sheet/prompt, for example. - `OnPageBusy` is excluded from the convention (obsolete in .NET 10, removed in .NET 11) and always routes to the fallback. - When .NET 11 ships a proper public `IAlertManager`/`IAlertDialogProvider`, this delegate convention can stay as a lightweight alias or be deprecated. Either way, .NET 10 consumers are unblocked now. ### Tests Unit coverage in `AlertManagerTests.cs` includes: - Alert, action sheet, and prompt delegate dispatch - Returned delegate results completing the original `Display*Async` caller - Unregistered operation fall-through - Unkeyed delegate services being ignored - Explicit `IAlertManagerSubscription` precedence - Synchronous and asynchronous delegate faults - Delegate cancellation forwarding - Null task contract violation Focused `AlertManagerTests` pass locally: 21/21. ### Issues Fixed Fixes #34104 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduces
IAlertManagerinterface to allow users to replace AlertManager behavior through dependency injection. Interface is internal with plans to make public in .NET 11.Changes
IAlertManagerinterface: Defines public contract for alert, action sheet, and prompt operationsSubscribe(),Unsubscribe(),RequestAlert(),RequestActionSheet(),RequestPrompt(),RequestPageBusy()AlertManagerimplementation: Now implementsIAlertManagerwithout behavioral changesWindow.AlertManagerproperty:AlertManagertoIAlertManagerinterface typeAlertManagerservices.AddSingleton<IAlertManager>(customImpl)Test updates: Cast to concrete type when accessing internal
SubscriptionpropertyMockServiceProviderfix: Returnsnullfor missing services instead of throwing (properIServiceProvidercontract)Usage Pattern
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.