diff --git a/src/Perspex.Controls/Primitives/TemplatedControl.cs b/src/Perspex.Controls/Primitives/TemplatedControl.cs index 7bf2edfbe7..10e312bb2b 100644 --- a/src/Perspex.Controls/Primitives/TemplatedControl.cs +++ b/src/Perspex.Controls/Primitives/TemplatedControl.cs @@ -251,7 +251,15 @@ namespace Perspex.Controls.Primitives { if (!_templateApplied) { - VisualChildren.Clear(); + if (VisualChildren.Count > 0) + { + foreach (var child in this.GetTemplateChildren()) + { + child.SetValue(TemplatedParentProperty, null); + } + + VisualChildren.Clear(); + } if (Template != null) { @@ -318,6 +326,11 @@ namespace Perspex.Controls.Primitives /// The event args. protected virtual void OnTemplateChanged(PerspexPropertyChangedEventArgs e) { + if (_templateApplied && VisualChildren.Count > 0) + { + _templateApplied = false; + } + _templateApplied = false; InvalidateMeasure(); } diff --git a/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs b/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs index 4de5d8fd3b..a93c6b3026 100644 --- a/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs +++ b/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs @@ -311,6 +311,39 @@ namespace Perspex.Controls.UnitTests.Primitives Assert.True(raised); } + [Fact] + public void Applying_New_Template_Clears_TemplatedParent_Of_Old_Template_Children() + { + var target = new TestTemplatedControl + { + Template = new FuncControlTemplate(_ => new Decorator + { + Child = new Border(), + }) + }; + + target.ApplyTemplate(); + + var decorator = (Decorator)target.GetVisualChildren().Single(); + var border = (Border)decorator.Child; + + Assert.Equal(target, decorator.TemplatedParent); + Assert.Equal(target, border.TemplatedParent); + + target.Template = new FuncControlTemplate(_ => new Canvas()); + + // Templated children should not be removed here: the control may be re-added + // somewhere with the same template, so they could still be of use. + Assert.Same(decorator, target.GetVisualChildren().Single()); + Assert.Equal(target, decorator.TemplatedParent); + Assert.Equal(target, border.TemplatedParent); + + target.ApplyTemplate(); + + Assert.Null(decorator.TemplatedParent); + Assert.Null(border.TemplatedParent); + } + private static IControl ScrollingContentControlTemplate(ContentControl control) { return new Border