From 39fd3af9cadab99e5c9a29e55475071e4ce79964 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 10 Dec 2019 15:11:37 +0100 Subject: [PATCH] Added sanity test for logical parent. Allows early detection of issue #3328. --- src/Avalonia.Styling/StyledElement.cs | 6 +++++ .../StyledElementTests.cs | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/Avalonia.Styling/StyledElement.cs b/src/Avalonia.Styling/StyledElement.cs index 5e1bcde2f6..9e61871f79 100644 --- a/src/Avalonia.Styling/StyledElement.cs +++ b/src/Avalonia.Styling/StyledElement.cs @@ -704,6 +704,12 @@ namespace Avalonia private void OnAttachedToLogicalTreeCore(LogicalTreeAttachmentEventArgs e) { + if (this.GetLogicalParent() == null && !(this is IStyleRoot)) + { + throw new InvalidOperationException( + $"AttachedToLogicalTreeCore called for '{GetType().Name}' but control has no logical parent."); + } + // This method can be called when a control is already attached to the logical tree // in the following scenario: // - ListBox gets assigned Items containing ListBoxItem diff --git a/tests/Avalonia.Styling.UnitTests/StyledElementTests.cs b/tests/Avalonia.Styling.UnitTests/StyledElementTests.cs index c40e6c735e..8e08c5ce36 100644 --- a/tests/Avalonia.Styling.UnitTests/StyledElementTests.cs +++ b/tests/Avalonia.Styling.UnitTests/StyledElementTests.cs @@ -76,6 +76,29 @@ namespace Avalonia.Styling.UnitTests Assert.Null(target.InheritanceParent); } + [Fact] + public void Adding_Element_With_Null_Parent_To_Logical_Tree_Should_Throw() + { + var target = new Border(); + var visualParent = new Panel(); + var logicalParent = new Panel(); + var root = new TestRoot(); + + // Set the logical parent... + ((ISetLogicalParent)target).SetParent(logicalParent); + + // ...so that when it's added to `visualParent`, the parent won't be set again. + visualParent.Children.Add(target); + + // Clear the logical parent. It's now a logical child of `visualParent` but doesn't have + // a logical parent itself. + ((ISetLogicalParent)target).SetParent(null); + + // In this case, attaching the control to a logical tree should throw. + logicalParent.Children.Add(visualParent); + Assert.Throws(() => root.Child = logicalParent); + } + [Fact] public void AttachedToLogicalParent_Should_Be_Called_When_Added_To_Tree() {