diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 54d7e76d73..81ed48f5b1 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -96,6 +96,10 @@ namespace Avalonia.Controls.Presenters /// public ContentPresenter() { + var dataContext = this.GetObservable(ContentProperty) + .Select(x => x is IControl ? AvaloniaProperty.UnsetValue : x); + + Bind(Control.DataContextProperty, dataContext); } /// @@ -217,72 +221,70 @@ namespace Avalonia.Controls.Presenters /// public void UpdateChild() { + var old = Child; var content = Content; - var oldChild = Child; - var newChild = content as IControl; + var result = content as IControl; - if (content != null && newChild == null) + if (result == null) { - // We have content and it isn't a control, so first try to recycle the existing - // child control to display the new data by querying if the template that created - // the child can recycle items and that it also matches the new data. - if (oldChild != null && - _dataTemplate != null && - _dataTemplate.SupportsRecycling && - _dataTemplate.Match(content)) - { - newChild = oldChild; - } - else + DataContext = content; + + if (content != null) { - // We couldn't recycle an existing control so find a data template for the data - // and use it to create a control. - _dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default; - newChild = _dataTemplate.Build(content); + if (old != null && + _dataTemplate != null && + _dataTemplate.SupportsRecycling && + _dataTemplate.Match(content)) + { + result = old; + } + else + { + _dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default; + result = _dataTemplate.Build(content); - // Try to give the new control its own name scope. - var controlResult = newChild as Control; + var controlResult = result as Control; - if (controlResult != null) - { - NameScope.SetNameScope(controlResult, new NameScope()); + if (controlResult != null) + { + NameScope.SetNameScope(controlResult, new NameScope()); + } } } + else + { + _dataTemplate = null; + } } else { _dataTemplate = null; } - // Remove the old child if we're not recycling it. - if (oldChild != null && newChild != oldChild) + if (result != old) { - VisualChildren.Remove(oldChild); - } + if (old != null) + { + VisualChildren.Remove(old); + } - // Set the DataContext if the data isn't a control. - if (!(content is IControl)) - { - DataContext = content; - } + if (result != null) + { + ((ISetInheritanceParent)result).SetParent(this); - // Update the Child. - if (newChild == null) - { - Child = null; - } - else if (newChild != oldChild) - { - ((ISetInheritanceParent)newChild).SetParent(this); + Child = result; - Child = newChild; + if (result.Parent == null) + { + ((ISetLogicalParent)result).SetParent((ILogical)this.TemplatedParent ?? this); + } - if (newChild.Parent == null) + VisualChildren.Add(result); + } + else { - ((ISetLogicalParent)newChild).SetParent((ILogical)this.TemplatedParent ?? this); + Child = null; } - - VisualChildren.Add(newChild); } _createdChild = true; diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index dcbc71b9a1..ce2dc4ab6c 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -370,7 +370,6 @@ namespace Avalonia.Controls.UnitTests target.Presenter.ApplyTemplate(); var dataContexts = target.Presenter.Panel.Children - .Do(x => (x as ContentPresenter)?.UpdateChild()) .Cast() .Select(x => x.DataContext) .ToList(); diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests.cs index 5c26ba5a5e..cd24631661 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests.cs @@ -143,15 +143,13 @@ namespace Avalonia.Controls.UnitTests.Presenters } [Fact] - public void Assigning_NonControl_To_Content_Should_Set_DataContext_On_UpdateChild() + public void Assigning_NonControl_To_Content_Should_Set_DataContext() { var target = new ContentPresenter { Content = "foo", }; - target.UpdateChild(); - Assert.Equal("foo", target.DataContext); } diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs index da1558439f..9f76767ec1 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs @@ -312,7 +312,6 @@ namespace Avalonia.Controls.UnitTests.Presenters var dataContexts = target.Panel.Children .Cast() - .Do(x => x.UpdateChild()) .Select(x => x.DataContext) .ToList();