public void Binding_ContentTemplate_After_Content_Does_Not_Leave_Orpaned_TextBlock() { // Test for #1271. var children = new List <IControl>(); var presenter = new ContentPresenter(); // The content and then the content template property need to be bound with delayed bindings // as they are in Avalonia.Markup.Xaml. DelayedBinding.Add(presenter, ContentPresenter.ContentProperty, new Binding("Content") { Priority = BindingPriority.TemplatedParent, RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), }); DelayedBinding.Add(presenter, ContentPresenter.ContentTemplateProperty, new Binding("ContentTemplate") { Priority = BindingPriority.TemplatedParent, RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), }); presenter.GetObservable(ContentPresenter.ChildProperty).Subscribe(children.Add); var target = new ContentControl { Template = new FuncControlTemplate <ContentControl>(_ => presenter), ContentTemplate = new FuncDataTemplate <string>(x => new Canvas()), Content = "foo", }; // The control must be rooted. var root = new TestRoot { Child = target, }; target.ApplyTemplate(); // When the template is applied, the Content property is bound before the ContentTemplate // property, causing a TextBlock to be created by the default template before ContentTemplate // is bound. Assert.Collection( children, x => Assert.Null(x), x => Assert.IsType <TextBlock>(x), x => Assert.IsType <Canvas>(x)); var textBlock = (TextBlock)children[1]; // The leak in #1271 was caused by the TextBlock's logical parent not being cleared when // it is replaced by the Canvas. Assert.Null(textBlock.GetLogicalParent()); }