From c8542d0fe142c03cdd8955062b25783550c2ba8e Mon Sep 17 00:00:00 2001 From: James Crutchley Date: Sat, 6 Dec 2025 07:16:01 -0800 Subject: [PATCH 1/8] Refactor Popup properties to use BindableProperty attribute Replaced manual BindableProperty implementations with the BindableProperty attribute in the `Popup` and `PopupOptions` classes. This simplifies property definitions, reduces boilerplate, and improves code readability. Updated properties such as `Margin`, `Padding`, `HorizontalOptions`, and `VerticalOptions` in `Popup`, and `CanBeDismissedByTappingOutsideOfPopup`, `OnTappingOutsideOfPopup`, `PageOverlayColor`, `Shape`, and `Shadow` in `PopupOptions` to use the attribute with default value creators. Removed redundant manual property implementations as they are now handled by the BindableProperty attribute. --- .../Views/Popup/Popup.shared.cs | 77 +++++-------------- .../Views/Popup/PopupOptions.shared.cs | 74 ++++++------------ 2 files changed, 45 insertions(+), 106 deletions(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs index a4485891af..2e67c42c19 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs @@ -1,3 +1,4 @@ +using System.ComponentModel; using CommunityToolkit.Maui.Extensions; namespace CommunityToolkit.Maui.Views; @@ -8,29 +9,38 @@ namespace CommunityToolkit.Maui.Views; public partial class Popup : ContentView { /// - /// Bindable property to set the margin between the and the edge of the window + /// Gets or sets the margin between the and the edge of the window. /// - public static new readonly BindableProperty MarginProperty = View.MarginProperty; + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultMargin))] + public partial Thickness Margin { get; set; } + static object CreateDefaultMargin(global::Microsoft.Maui.Controls.BindableObject? _) => View.MarginProperty; /// - /// Bindable property to set the padding between the border and the content + /// Gets or sets the padding between the border and the content. /// - public static new readonly BindableProperty PaddingProperty = ContentView.PaddingProperty; + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultPadding))] + public partial Thickness Padding { get; set; } + static object CreateDefaultPadding(global::Microsoft.Maui.Controls.BindableObject? _) => ContentView.PaddingProperty; /// - /// Bindable property to set the horizontal position of the when displayed on screen + /// Gets or sets the horizontal layout options used to position the when displayed on screen. /// - public static new readonly BindableProperty HorizontalOptionsProperty = View.HorizontalOptionsProperty; + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultHorizontalOptions))] + public partial LayoutOptions HorizontalOptions { get; set; } + static object CreateDefaultHorizontalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => View.HorizontalOptionsProperty; /// - /// Bindable property to set the vertical position of the when displayed on screen + /// Gets or sets the vertical layout options used to position the when displayed on screen. /// - public static new readonly BindableProperty VerticalOptionsProperty = View.VerticalOptionsProperty; + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultVerticalOptions))] + public partial LayoutOptions VerticalOptions { get; set; } + static object CreateDefaultVerticalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => View.VerticalOptionsProperty; /// - /// Backing BindableProperty for the property. + /// Gets or sets a value indicating whether the can be dismissed by tapping outside of the popup. /// - public static readonly BindableProperty CanBeDismissedByTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(CanBeDismissedByTappingOutsideOfPopup), typeof(bool), typeof(Popup), Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup); + [BindableProperty(DefaultValue = PopupDefaults.CanBeDismissedByTappingOutsideOfPopup)] + public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } /// /// Initializes Popup @@ -54,53 +64,6 @@ public Popup() /// public event EventHandler? Closed; - /// - /// Sets the margin between the and the edge of the window - /// - public new Thickness Margin - { - get => base.Margin; - set => base.Margin = value; - } - - /// - /// Sets the padding between the border and the content - /// - public new Thickness Padding - { - get => base.Padding; - set => base.Padding = value; - } - - /// - /// Sets the horizontal position of the when displayed on screen - /// - public new LayoutOptions HorizontalOptions - { - get => base.HorizontalOptions; - set => base.HorizontalOptions = value; - } - - /// - /// Sets the vertical position of the when displayed on screen - /// - public new LayoutOptions VerticalOptions - { - get => base.VerticalOptions; - set => base.VerticalOptions = value; - } - - /// /> - /// - /// When true and the user taps outside the popup, it will dismiss. - /// On Android - when false the hardware back button is disabled. - /// - public bool CanBeDismissedByTappingOutsideOfPopup - { - get => (bool)GetValue(CanBeDismissedByTappingOutsideOfPopupProperty); - set => SetValue(CanBeDismissedByTappingOutsideOfPopupProperty, value); - } - /// /// Close the Popup. /// diff --git a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs index 285bf517fe..c5d85cb23b 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs @@ -8,71 +8,47 @@ namespace CommunityToolkit.Maui; public partial class PopupOptions : BindableObject, IPopupOptions { /// - /// Backing BindableProperty for the property. + /// Gets or sets a value indicating whether the popup can be dismissed by tapping outside of the popup. + /// Default is provided by . /// - public static readonly BindableProperty CanBeDismissedByTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(CanBeDismissedByTappingOutsideOfPopup), typeof(bool), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup); + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateCanBeDismissedByTappingOutsideOfPopup))] + public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } + static object CreateCanBeDismissedByTappingOutsideOfPopup(BindableObject? _) => Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup; /// - /// Backing BindableProperty for the property. + /// Gets or sets an invoked when the user taps outside of the popup. + /// Default is provided by . /// - public static readonly BindableProperty OnTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(OnTappingOutsideOfPopup), typeof(Action), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup); + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateOnTappingOutsideOfPopup))] + public partial Action OnTappingOutsideOfPopup { get; set; } + static object? CreateOnTappingOutsideOfPopup(BindableObject? _) => Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup; /// - /// Backing BindableProperty for the property. + /// Gets or sets the overlay applied to the page while the popup is displayed. + /// Default is provided by . /// - public static readonly BindableProperty PageOverlayColorProperty = BindableProperty.Create(nameof(PageOverlayColor), typeof(Color), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.PageOverlayColor); + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreatePageOverlayColor))] + public partial Color PageOverlayColor { get; set; } + static object CreatePageOverlayColor(BindableObject? _) => Options.DefaultPopupOptionsSettings.PageOverlayColor; /// - /// Backing BindableProperty for the property. + /// Gets or sets the used to render the popup's outline. + /// Default is provided by . /// - public static readonly BindableProperty ShapeProperty = BindableProperty.Create(nameof(Shape), typeof(Shape), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.Shape); + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateShape))] + public partial Shape? Shape { get; set; } + static object? CreateShape(BindableObject? _) => Options.DefaultPopupOptionsSettings.Shape; /// - /// Backing BindableProperty for the property. + /// Gets or sets the applied to the popup. + /// Default is provided by . /// - public static readonly BindableProperty ShadowProperty = BindableProperty.Create(nameof(Shadow), typeof(Shadow), typeof(PopupOptions), Options.DefaultPopupOptionsSettings.Shadow); + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateShadow))] + public partial Shadow? Shadow { get; set; } + static object? CreateShadow(BindableObject? _) => Options.DefaultPopupOptionsSettings.Shadow; /// /// An empty instance of containing default values. /// public static IPopupOptions Empty { get; } = new PopupOptions(); - - /// - /// - /// When true and the user taps outside the popup, it will dismiss. - /// On Android - when false the hardware back button is disabled. - /// - public bool CanBeDismissedByTappingOutsideOfPopup - { - get => (bool)GetValue(CanBeDismissedByTappingOutsideOfPopupProperty); - set => SetValue(CanBeDismissedByTappingOutsideOfPopupProperty, value); - } - - /// - public Color PageOverlayColor - { - get => (Color)GetValue(PageOverlayColorProperty); - set => SetValue(PageOverlayColorProperty, value); - } - - /// - public Action? OnTappingOutsideOfPopup - { - get => (Action?)GetValue(OnTappingOutsideOfPopupProperty); - set => SetValue(OnTappingOutsideOfPopupProperty, value); - } - - /// - public Shape? Shape - { - get => (Shape?)GetValue(ShapeProperty); - set => SetValue(ShapeProperty, value); - } - - /// - public Shadow? Shadow - { - get => (Shadow?)GetValue(ShadowProperty); - set => SetValue(ShadowProperty, value); - } } \ No newline at end of file From 61e0665cf3656bd5b821dbf2c9266ef26e490911 Mon Sep 17 00:00:00 2001 From: James Crutchley Date: Sat, 6 Dec 2025 08:37:38 -0800 Subject: [PATCH 2/8] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs index 2e67c42c19..a5601568c1 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs @@ -13,28 +13,28 @@ public partial class Popup : ContentView /// [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultMargin))] public partial Thickness Margin { get; set; } - static object CreateDefaultMargin(global::Microsoft.Maui.Controls.BindableObject? _) => View.MarginProperty; + static object CreateDefaultMargin(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.Margin; /// /// Gets or sets the padding between the border and the content. /// [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultPadding))] public partial Thickness Padding { get; set; } - static object CreateDefaultPadding(global::Microsoft.Maui.Controls.BindableObject? _) => ContentView.PaddingProperty; + static object CreateDefaultPadding(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.Padding; /// /// Gets or sets the horizontal layout options used to position the when displayed on screen. /// [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultHorizontalOptions))] public partial LayoutOptions HorizontalOptions { get; set; } - static object CreateDefaultHorizontalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => View.HorizontalOptionsProperty; + static object CreateDefaultHorizontalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.HorizontalOptions; /// /// Gets or sets the vertical layout options used to position the when displayed on screen. /// [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultVerticalOptions))] public partial LayoutOptions VerticalOptions { get; set; } - static object CreateDefaultVerticalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => View.VerticalOptionsProperty; + static object CreateDefaultVerticalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.VerticalOptions; /// /// Gets or sets a value indicating whether the can be dismissed by tapping outside of the popup. From d25d65b1a48a9430335322461517e8fc3847856f Mon Sep 17 00:00:00 2001 From: James Crutchley Date: Sat, 6 Dec 2025 08:41:03 -0800 Subject: [PATCH 3/8] Update src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs index c5d85cb23b..4016c575b7 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs @@ -20,7 +20,7 @@ public partial class PopupOptions : BindableObject, IPopupOptions /// Default is provided by . /// [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateOnTappingOutsideOfPopup))] - public partial Action OnTappingOutsideOfPopup { get; set; } + public partial Action? OnTappingOutsideOfPopup { get; set; } static object? CreateOnTappingOutsideOfPopup(BindableObject? _) => Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup; /// From 4ce65423510b6993b5320339126143708c6c8819 Mon Sep 17 00:00:00 2001 From: James Crutchley Date: Sat, 6 Dec 2025 08:43:59 -0800 Subject: [PATCH 4/8] Refactor Popup property default value handling Updated the `CanBeDismissedByTappingOutsideOfPopup` property to use a `DefaultValueCreatorMethodName` for dynamic default value resolution. Added the `CreateCanBeDismissedByTappingOutsideOfPopup` method to provide the default value at runtime, improving flexibility and reducing reliance on hardcoded defaults. --- src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs index a5601568c1..b9689f675a 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs @@ -39,8 +39,10 @@ public partial class Popup : ContentView /// /// Gets or sets a value indicating whether the can be dismissed by tapping outside of the popup. /// - [BindableProperty(DefaultValue = PopupDefaults.CanBeDismissedByTappingOutsideOfPopup)] + [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateCanBeDismissedByTappingOutsideOfPopup))] public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } + static object CreateCanBeDismissedByTappingOutsideOfPopup(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup; + /// /// Initializes Popup From 537651635d3729d3efb153d09b7b157b60dd15d7 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:26:10 -0800 Subject: [PATCH 5/8] Use partial property initializers --- .../Views/Popup/Popup.shared.cs | 64 +++++++++---------- .../Views/Popup/PopupOptions.shared.cs | 39 +++++------ 2 files changed, 47 insertions(+), 56 deletions(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs index b9689f675a..0b43dd60ea 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs @@ -9,62 +9,56 @@ namespace CommunityToolkit.Maui.Views; public partial class Popup : ContentView { /// - /// Gets or sets the margin between the and the edge of the window. + /// Initializes Popup /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultMargin))] - public partial Thickness Margin { get; set; } - static object CreateDefaultMargin(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.Margin; + public Popup() + { + Margin = Options.DefaultPopupSettings.Margin; + Padding = Options.DefaultPopupSettings.Padding; + HorizontalOptions = Options.DefaultPopupSettings.HorizontalOptions; + VerticalOptions = Options.DefaultPopupSettings.VerticalOptions; + BackgroundColor = Options.DefaultPopupSettings.BackgroundColor; + } /// - /// Gets or sets the padding between the border and the content. + /// Event occurs when is opened. /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultPadding))] - public partial Thickness Padding { get; set; } - static object CreateDefaultPadding(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.Padding; + public event EventHandler? Opened; /// - /// Gets or sets the horizontal layout options used to position the when displayed on screen. + /// Event occurs when is closed. /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultHorizontalOptions))] - public partial LayoutOptions HorizontalOptions { get; set; } - static object CreateDefaultHorizontalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.HorizontalOptions; + public event EventHandler? Closed; /// - /// Gets or sets the vertical layout options used to position the when displayed on screen. + /// Gets or sets the margin between the and the edge of the window. /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateDefaultVerticalOptions))] - public partial LayoutOptions VerticalOptions { get; set; } - static object CreateDefaultVerticalOptions(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.VerticalOptions; + [BindableProperty] + public new partial Thickness Margin { get; set; } = Options.DefaultPopupSettings.Margin; /// - /// Gets or sets a value indicating whether the can be dismissed by tapping outside of the popup. + /// Gets or sets the padding between the border and the content. /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateCanBeDismissedByTappingOutsideOfPopup))] - public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } - static object CreateCanBeDismissedByTappingOutsideOfPopup(global::Microsoft.Maui.Controls.BindableObject? _) => Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup; - + [BindableProperty] + public new partial Thickness Padding { get; set; } = Options.DefaultPopupSettings.Padding; /// - /// Initializes Popup + /// Gets or sets the horizontal layout options used to position the when displayed on screen. /// - public Popup() - { - Margin = Options.DefaultPopupSettings.Margin; - Padding = Options.DefaultPopupSettings.Padding; - HorizontalOptions = Options.DefaultPopupSettings.HorizontalOptions; - VerticalOptions = Options.DefaultPopupSettings.VerticalOptions; - BackgroundColor = Options.DefaultPopupSettings.BackgroundColor; - } + [BindableProperty] + public new partial LayoutOptions HorizontalOptions { get; set; } = Options.DefaultPopupSettings.HorizontalOptions; /// - /// Event occurs when is opened. + /// Gets or sets the vertical layout options used to position the when displayed on screen. /// - public event EventHandler? Opened; + [BindableProperty] + public new partial LayoutOptions VerticalOptions { get; set; } = Options.DefaultPopupSettings.VerticalOptions; /// - /// Event occurs when is closed. + /// Gets or sets a value indicating whether the can be dismissed by tapping outside the popup. /// - public event EventHandler? Closed; + [BindableProperty] + public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } = Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup; /// /// Close the Popup. @@ -113,5 +107,7 @@ public partial class Popup : Popup } sealed class PopupNotFoundException() : InvalidPopupOperationException($"Unable to close popup: could not locate {nameof(PopupPage)}. {nameof(PopupExtensions.ShowPopup)} or {nameof(PopupExtensions.ShowPopupAsync)} must be called before {nameof(Popup.CloseAsync)}. If using a custom implementation of {nameof(Popup)}, override the {nameof(Popup.CloseAsync)} method"); + sealed class PopupBlockedException(in Page currentVisibleModalPage) : InvalidPopupOperationException($"Unable to close Popup because it is blocked by the Modal Page {currentVisibleModalPage.GetType().FullName}. Please call `{nameof(Page.Navigation)}.{nameof(Page.Navigation.PopModalAsync)}()` to first remove {currentVisibleModalPage.GetType().FullName} from the {nameof(Page.Navigation.ModalStack)}"); + class InvalidPopupOperationException(in string message) : InvalidOperationException(message); \ No newline at end of file diff --git a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs index 4016c575b7..54b118e969 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs @@ -8,47 +8,42 @@ namespace CommunityToolkit.Maui; public partial class PopupOptions : BindableObject, IPopupOptions { /// - /// Gets or sets a value indicating whether the popup can be dismissed by tapping outside of the popup. + /// An empty instance of containing default values. + /// + public static IPopupOptions Empty { get; } = new PopupOptions(); + + /// + /// Gets or sets a value indicating whether the popup can be dismissed by tapping outside the popup. /// Default is provided by . /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateCanBeDismissedByTappingOutsideOfPopup))] - public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } - static object CreateCanBeDismissedByTappingOutsideOfPopup(BindableObject? _) => Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup; + [BindableProperty] + public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } = Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup; /// - /// Gets or sets an invoked when the user taps outside of the popup. + /// Gets or sets an invoked when the user taps outside the popup. /// Default is provided by . /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateOnTappingOutsideOfPopup))] - public partial Action? OnTappingOutsideOfPopup { get; set; } - static object? CreateOnTappingOutsideOfPopup(BindableObject? _) => Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup; + [BindableProperty] + public partial Action? OnTappingOutsideOfPopup { get; set; } = Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup; /// /// Gets or sets the overlay applied to the page while the popup is displayed. /// Default is provided by . /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreatePageOverlayColor))] - public partial Color PageOverlayColor { get; set; } - static object CreatePageOverlayColor(BindableObject? _) => Options.DefaultPopupOptionsSettings.PageOverlayColor; + [BindableProperty] + public partial Color PageOverlayColor { get; set; } = Options.DefaultPopupOptionsSettings.PageOverlayColor; /// /// Gets or sets the used to render the popup's outline. /// Default is provided by . /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateShape))] - public partial Shape? Shape { get; set; } - static object? CreateShape(BindableObject? _) => Options.DefaultPopupOptionsSettings.Shape; + [BindableProperty] + public partial Shape? Shape { get; set; } = Options.DefaultPopupOptionsSettings.Shape; /// /// Gets or sets the applied to the popup. /// Default is provided by . /// - [BindableProperty(DefaultValueCreatorMethodName = nameof(CreateShadow))] - public partial Shadow? Shadow { get; set; } - static object? CreateShadow(BindableObject? _) => Options.DefaultPopupOptionsSettings.Shadow; - - /// - /// An empty instance of containing default values. - /// - public static IPopupOptions Empty { get; } = new PopupOptions(); + [BindableProperty] + public partial Shadow? Shadow { get; set; } = Options.DefaultPopupOptionsSettings.Shadow; } \ No newline at end of file From 88c89c6ad34ec27c3d248f5dc5ceaf4676a5dd71 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:39:27 -0800 Subject: [PATCH 6/8] Fix XML Comments --- .../Views/Popup/Popup.shared.cs | 12 ++++---- .../Views/Popup/PopupOptions.shared.cs | 29 ++++++------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs index 0b43dd60ea..4c15bb2560 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs @@ -43,20 +43,22 @@ public Popup() public new partial Thickness Padding { get; set; } = Options.DefaultPopupSettings.Padding; /// - /// Gets or sets the horizontal layout options used to position the when displayed on screen. + /// Gets or sets the horizontal position of the when displayed on screen. /// [BindableProperty] public new partial LayoutOptions HorizontalOptions { get; set; } = Options.DefaultPopupSettings.HorizontalOptions; /// - /// Gets or sets the vertical layout options used to position the when displayed on screen. + /// Gets or sets the vertical position of the when displayed on screen. /// [BindableProperty] public new partial LayoutOptions VerticalOptions { get; set; } = Options.DefaultPopupSettings.VerticalOptions; - /// - /// Gets or sets a value indicating whether the can be dismissed by tapping outside the popup. - /// + /// /> + /// + /// When true and the user taps outside the popup, it will dismiss. + /// On Android - when false the hardware back button is disabled. + /// [BindableProperty] public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } = Options.DefaultPopupSettings.CanBeDismissedByTappingOutsideOfPopup; diff --git a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs index 54b118e969..6e96c873b4 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/PopupOptions.shared.cs @@ -12,38 +12,27 @@ public partial class PopupOptions : BindableObject, IPopupOptions /// public static IPopupOptions Empty { get; } = new PopupOptions(); - /// - /// Gets or sets a value indicating whether the popup can be dismissed by tapping outside the popup. - /// Default is provided by . - /// + /// + /// + /// When true and the user taps outside the popup, it will dismiss. + /// On Android - when false the hardware back button is disabled. + /// [BindableProperty] public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; } = Options.DefaultPopupOptionsSettings.CanBeDismissedByTappingOutsideOfPopup; - /// - /// Gets or sets an invoked when the user taps outside the popup. - /// Default is provided by . - /// + /// [BindableProperty] public partial Action? OnTappingOutsideOfPopup { get; set; } = Options.DefaultPopupOptionsSettings.OnTappingOutsideOfPopup; - /// - /// Gets or sets the overlay applied to the page while the popup is displayed. - /// Default is provided by . - /// + /// [BindableProperty] public partial Color PageOverlayColor { get; set; } = Options.DefaultPopupOptionsSettings.PageOverlayColor; - /// - /// Gets or sets the used to render the popup's outline. - /// Default is provided by . - /// + /// [BindableProperty] public partial Shape? Shape { get; set; } = Options.DefaultPopupOptionsSettings.Shape; - /// - /// Gets or sets the applied to the popup. - /// Default is provided by . - /// + /// [BindableProperty] public partial Shadow? Shadow { get; set; } = Options.DefaultPopupOptionsSettings.Shadow; } \ No newline at end of file From 0945a9a852c44dc87687e7e5c79586502f1de252 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:44:03 -0800 Subject: [PATCH 7/8] Fix Failing Unit Tests --- .../Extensions/PopupExtensionsTests.cs | 4 ++-- .../Services/PopupServiceTests.cs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs index a80cf53c5b..7391f8bf97 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs @@ -445,7 +445,7 @@ public void ShowPopupAsync_WithCustomOptions_AppliesOptions() var popupPage = (PopupPage)navigation.ModalStack[0]; var popupPageContent = popupPage.Content; var border = popupPageContent.PopupBorder; - var popup = border.Content; + var popup = (Popup)(border.Content ?? throw new InvalidOperationException("Content cannot be null")); // Assert Assert.NotNull(popup); @@ -516,7 +516,7 @@ public void ShowPopupAsync_Shell_WithCustomOptions_AppliesOptions() var popupPage = (PopupPage)shellNavigation.ModalStack[0]; var popupPageContent = popupPage.Content; var border = popupPageContent.PopupBorder; - var popup = border.Content; + var popup = (ShortLivedSelfClosingPopup)(border.Content ?? throw new InvalidOperationException("Content cannot be null")); // Assert Assert.NotNull(popup); diff --git a/src/CommunityToolkit.Maui.UnitTests/Services/PopupServiceTests.cs b/src/CommunityToolkit.Maui.UnitTests/Services/PopupServiceTests.cs index d9e1b7bb06..d8d84d1257 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Services/PopupServiceTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Services/PopupServiceTests.cs @@ -165,7 +165,7 @@ public void ShowPopupAsync_WithCustomOptions_AppliesOptions() var popupPage = (PopupPage)navigation.ModalStack[0]; var popupPageLayout = popupPage.Content; var border = popupPageLayout.PopupBorder; - var popup = border.Content; + var popup = (MockPopup)(border.Content ?? throw new InvalidOperationException("Content cannot be null")); // Assert Assert.NotNull(popup); @@ -515,7 +515,6 @@ public async Task ClosePopupAsyncT_ShouldClosePopupUsingPageAndReturnResult() } } - class GarbageCollectionHeavySelfClosingPopup(MockPageViewModel viewModel, object? result = null) : MockSelfClosingPopup(viewModel, TimeSpan.FromMilliseconds(500), result) { protected override void HandlePopupOpened(object? sender, EventArgs e) From 4e248f68589bbda22dda4a11a5cefc3db8842a3c Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+TheCodeTraveler@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:44:46 -0800 Subject: [PATCH 8/8] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs index 4c15bb2560..820d6751df 100644 --- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs +++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; + using CommunityToolkit.Maui.Extensions; namespace CommunityToolkit.Maui.Views;