From 546cbca0eff72adbfb15e962fc5ef2c8ef0258eb Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Dec 2017 12:39:55 +0100 Subject: [PATCH 1/2] Added failing test for #1247. --- .../Primitives/PopupRootTests.cs | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) 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(); + } + } } } From d1ebb8fc7d4360b1f10dcadeba2039e07dc22442 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Dec 2017 12:43:00 +0100 Subject: [PATCH 2/2] Handle PopupRoot.Content = null. Handle `PopupRoot.Content` being set to null. Fixes #1247 --- src/Avalonia.Controls/Primitives/PopupRoot.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) 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); + } } } }