diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index a999e4ae37..00d43500c3 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -90,20 +90,23 @@ namespace Avalonia.Controls.Primitives private void SetTemplatedParentAndApplyChildTemplates(IControl control) { - var templatedParent = Parent.TemplatedParent; - - if (control.TemplatedParent == null) + if (control != null) { - control.SetValue(TemplatedParentProperty, templatedParent); - } + var templatedParent = Parent.TemplatedParent; + + if (control.TemplatedParent == null) + { + control.SetValue(TemplatedParentProperty, templatedParent); + } - control.ApplyTemplate(); + control.ApplyTemplate(); - if (!(control is IPresenter) && control.TemplatedParent == templatedParent) - { - foreach (IControl child in control.GetVisualChildren()) + if (!(control is IPresenter) && control.TemplatedParent == templatedParent) { - SetTemplatedParentAndApplyChildTemplates(child); + foreach (IControl child in control.GetVisualChildren()) + { + SetTemplatedParentAndApplyChildTemplates(child); + } } } } diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index 64344a1584..b3f91ce937 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -2,11 +2,13 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Linq; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.LogicalTree; using Avalonia.UnitTests; +using Avalonia.VisualTree; using Xunit; namespace Avalonia.Controls.UnitTests.Primitives @@ -90,14 +92,33 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + [Fact] + public void Clearing_Content_Of_Popup_In_ControlTemplate_Doesnt_Crash() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var target = new TemplatedControlWithPopup + { + PopupContent = new Canvas(), + }; + + var root = new TestRoot { Child = target }; + + target.ApplyTemplate(); + target.Popup.Open(); + target.PopupContent = null; + } + } + private PopupRoot CreateTarget() { var result = new PopupRoot { - Template = new FuncControlTemplate(_ => + Template = new FuncControlTemplate(parent => new ContentPresenter { Name = "PART_ContentPresenter", + [!ContentPresenter.ContentProperty] = parent[!PopupRoot.ContentProperty], }), }; @@ -105,5 +126,33 @@ namespace Avalonia.Controls.UnitTests.Primitives return result; } + + private class TemplatedControlWithPopup : TemplatedControl + { + public static readonly AvaloniaProperty PopupContentProperty = + AvaloniaProperty.Register(nameof(PopupContent)); + + public TemplatedControlWithPopup() + { + Template = new FuncControlTemplate(parent => + new Popup + { + [!Popup.ChildProperty] = parent[!TemplatedControlWithPopup.PopupContentProperty], + }); + } + + public Popup Popup { get; private set; } + + public Control PopupContent + { + get => GetValue(PopupContentProperty); + set => SetValue(PopupContentProperty, value); + } + + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) + { + Popup = (Popup)this.GetVisualChildren().Single(); + } + } } }