Browse Source

Revert "Revert "Set ContentPresenter.DataContext in UpdateChild.""

This reverts commit bf02ae41a9050a2e2db21dadb9970d9248424f99.
Steven Kirk 9 years ago
parent
commit
7b3e25949e

+ 45 - 47
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@@ -96,10 +96,6 @@ namespace Avalonia.Controls.Presenters
         /// </summary>
         public ContentPresenter()
         {
-            var dataContext = this.GetObservable(ContentProperty)
-                .Select(x => x is IControl ? AvaloniaProperty.UnsetValue : x);
-
-            Bind(Control.DataContextProperty, dataContext);
         }
 
         /// <summary>
@@ -221,39 +217,36 @@ namespace Avalonia.Controls.Presenters
         /// </remarks>
         public void UpdateChild()
         {
-            var old = Child;
             var content = Content;
-            var result = content as IControl;
+            var oldChild = Child;
+            var newChild = content as IControl;
 
-            if (result == null)
+            if (content != null && newChild == null)
             {
-                DataContext = content;
-
-                if (content != 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))
                 {
-                    if (old != null && 
-                        _dataTemplate != null &&
-                        _dataTemplate.SupportsRecycling && 
-                        _dataTemplate.Match(content))
-                    {
-                        result = old;
-                    }
-                    else
-                    {
-                        _dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default;
-                        result = _dataTemplate.Build(content);
-
-                        var controlResult = result as Control;
-
-                        if (controlResult != null)
-                        {
-                            NameScope.SetNameScope(controlResult, new NameScope());
-                        }
-                    }
+                    newChild = oldChild;
                 }
                 else
                 {
-                    _dataTemplate = 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);
+
+                    // Try to give the new control its own name scope.
+                    var controlResult = newChild as Control;
+
+                    if (controlResult != null)
+                    {
+                        NameScope.SetNameScope(controlResult, new NameScope());
+                    }
                 }
             }
             else
@@ -261,30 +254,35 @@ namespace Avalonia.Controls.Presenters
                 _dataTemplate = null;
             }
 
-            if (result != old)
+            // Remove the old child if we're not recycling it.
+            if (oldChild != null && newChild != oldChild)
             {
-                if (old != null)
-                {
-                    VisualChildren.Remove(old);
-                }
+                VisualChildren.Remove(oldChild);
+            }
 
-                if (result != null)
-                {
-                    ((ISetInheritanceParent)result).SetParent(this);
+            // Set the DataContext if the data isn't a control.
+            if (!(content is IControl))
+            {
+                DataContext = content;
+            }
 
-                    Child = result;
+            // Update the Child.
+            if (newChild == null)
+            {
+                Child = null;
+            }
+            else if (newChild != oldChild)
+            {
+                ((ISetInheritanceParent)newChild).SetParent(this);
 
-                    if (result.Parent == null)
-                    {
-                        ((ISetLogicalParent)result).SetParent((ILogical)this.TemplatedParent ?? this);
-                    }
+                Child = newChild;
 
-                    VisualChildren.Add(result);
-                }
-                else
+                if (newChild.Parent == null)
                 {
-                    Child = null;
+                    ((ISetLogicalParent)newChild).SetParent((ILogical)this.TemplatedParent ?? this);
                 }
+
+                VisualChildren.Add(newChild);
             }
 
             _createdChild = true;

+ 1 - 0
tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

@@ -370,6 +370,7 @@ namespace Avalonia.Controls.UnitTests
             target.Presenter.ApplyTemplate();
 
             var dataContexts = target.Presenter.Panel.Children
+                .Do(x => (x as ContentPresenter)?.UpdateChild())
                 .Cast<Control>()
                 .Select(x => x.DataContext)
                 .ToList();

+ 3 - 1
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests.cs

@@ -143,13 +143,15 @@ namespace Avalonia.Controls.UnitTests.Presenters
         }
 
         [Fact]
-        public void Assigning_NonControl_To_Content_Should_Set_DataContext()
+        public void Assigning_NonControl_To_Content_Should_Set_DataContext_On_UpdateChild()
         {
             var target = new ContentPresenter
             {
                 Content = "foo",
             };
 
+            target.UpdateChild();
+
             Assert.Equal("foo", target.DataContext);
         }
 

+ 1 - 0
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

@@ -312,6 +312,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
 
             var dataContexts = target.Panel.Children
                 .Cast<ContentPresenter>()
+                .Do(x => x.UpdateChild())
                 .Select(x => x.DataContext)
                 .ToList();