Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure Popup will set the Window at the Content #674

Merged
merged 8 commits into from
Oct 18, 2022
2 changes: 1 addition & 1 deletion src/CommunityToolkit.Maui.Core/Interfaces/IPopup.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace CommunityToolkit.Maui.Core;
/// <summary>
/// Represents a small View that pops up at front the Page.
/// </summary>
public interface IPopup : IElement
public interface IPopup : IElement, IVisualTreeElement
{
/// <summary>
/// Gets the View that Popup will be anchored.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ static PageHandler CreatePageHandler(IPopup virtualView)
var view = (View?)virtualView.Content ?? throw new InvalidOperationException($"{nameof(IPopup.Content)} can't be null here.");
var contentPage = new ContentPage
{
Content = view,
Parent = Application.Current?.MainPage
Content = view
};

contentPage.SetBinding(BindingContextProperty, new Binding { Source = virtualView, Path = BindingContextProperty.PropertyName });
Expand Down
32 changes: 30 additions & 2 deletions src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CommunityToolkit.Maui.Core;
using Microsoft.Maui.Controls.Internals;
using LayoutAlignment = Microsoft.Maui.Primitives.LayoutAlignment;

namespace CommunityToolkit.Maui.Views;
Expand All @@ -7,7 +8,7 @@ namespace CommunityToolkit.Maui.Views;
/// Represents a small View that pops up at front the Page. Implements <see cref="IPopup"/>.
/// </summary>
[ContentProperty(nameof(Content))]
public partial class Popup : Element, IPopup
public partial class Popup : Element, IPopup, IWindowController, IPropertyPropagationController
{
/// <summary>
/// Backing BindableProperty for the <see cref="Content"/> property.
Expand Down Expand Up @@ -44,6 +45,7 @@ public partial class Popup : Element, IPopup
readonly Lazy<PlatformConfigurationRegistry<Popup>> platformConfigurationRegistry;

TaskCompletionSource<object?> taskCompletionSource = new();
Window? window;

/// <summary>
/// Instantiates a new instance of <see cref="Popup"/>.
Expand All @@ -53,7 +55,6 @@ public Popup()
platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<Popup>>(() => new(this));

VerticalOptions = HorizontalOptions = LayoutAlignment.Center;

#if WINDOWS
this.HandlerChanged += OnPopupHandlerChanged;
#endif
Expand Down Expand Up @@ -163,6 +164,23 @@ public bool CanBeDismissedByTappingOutsideOfPopup
/// </remarks>
public View? Anchor { get; set; }

/// <summary>
/// Property that represents the Window that's showing the Popup.
/// </summary>
public Window? Window
{
get => window;
set
{
window = value;

if (Content is IWindowController controller)
{
controller.Window = value;
}
}
}

/// <summary>
/// Gets or sets the result that will return when user taps outside of the Popup.
/// </summary>
Expand All @@ -174,6 +192,7 @@ public bool CanBeDismissedByTappingOutsideOfPopup
/// <inheritdoc/>
IView? IPopup.Content => Content;


/// <summary>
/// Resets the Popup.
/// </summary>
Expand Down Expand Up @@ -231,6 +250,7 @@ protected override void OnBindingContextChanged()
if (Content is not null)
{
SetInheritedBindingContext(Content, BindingContext);
Content.Parent = this;
}
}

Expand All @@ -250,4 +270,12 @@ static void OnColorChanged(BindableObject bindable, object oldValue, object newV
void IPopup.OnOpened() => OnOpened();

void IPopup.OnDismissedByTappingOutsideOfPopup() => OnDismissedByTappingOutsideOfPopup();

void IPropertyPropagationController.PropagatePropertyChanged(string propertyName) =>
PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, ((IVisualTreeElement)this).GetVisualChildren());

IReadOnlyList<IVisualTreeElement> IVisualTreeElement.GetVisualChildren() =>
Content is null
? Enumerable.Empty<IVisualTreeElement>().ToList()
: new List<IVisualTreeElement> { Content };
}