diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index dd047db279..b0db89f7ea 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -26,7 +26,7 @@ namespace Avalonia
///
/// The parent object that inherited values are inherited from.
///
- private AvaloniaObject _inheritanceParent;
+ private IAvaloniaObject _inheritanceParent;
///
/// The set values/bindings on this object.
@@ -120,7 +120,7 @@ namespace Avalonia
///
/// The inheritance parent.
///
- protected AvaloniaObject InheritanceParent
+ protected IAvaloniaObject InheritanceParent
{
get
{
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index 80d29b14ab..22d17bf633 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -58,6 +58,7 @@
+
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index e246635906..0bede31fb4 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -33,7 +33,7 @@ namespace Avalonia.Controls
/// - Implements to allow styling to work on the control.
/// - Implements to form part of a logical tree.
///
- public class Control : InputElement, IControl, INamed, ISetLogicalParent, ISupportInitialize
+ public class Control : InputElement, IControl, INamed, ISetInheritanceParent, ISetLogicalParent, ISupportInitialize
{
///
/// Defines the property.
@@ -455,6 +455,15 @@ namespace Avalonia.Controls
}
}
+ ///
+ /// Sets the control's inheritance parent.
+ ///
+ /// The parent.
+ void ISetInheritanceParent.SetParent(IAvaloniaObject parent)
+ {
+ InheritanceParent = parent;
+ }
+
///
/// Adds a pseudo-class to be set when a property is true.
///
diff --git a/src/Avalonia.Controls/ISetInheritanceParent.cs b/src/Avalonia.Controls/ISetInheritanceParent.cs
new file mode 100644
index 0000000000..788ab77246
--- /dev/null
+++ b/src/Avalonia.Controls/ISetInheritanceParent.cs
@@ -0,0 +1,22 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+namespace Avalonia.Controls
+{
+ ///
+ /// Defines an interface through which a 's inheritance parent can be set.
+ ///
+ ///
+ /// You should not usually need to use this interface - it is for advanced scenarios only.
+ /// Additionally, also sets the inheritance parent; this
+ /// interface is only needed where the logical and inheritance parents differ.
+ ///
+ public interface ISetInheritanceParent
+ {
+ ///
+ /// Sets the control's inheritance parent.
+ ///
+ /// The parent.
+ void SetParent(IAvaloniaObject parent);
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
index 3470a43c1c..87435319c7 100644
--- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
@@ -80,6 +80,7 @@ namespace Avalonia.Controls.Presenters
private IControl _child;
private bool _createdChild;
+ private IDataTemplate _dataTemplate;
///
/// Initializes static members of the class.
@@ -200,6 +201,13 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+ _dataTemplate = null;
+ }
+
///
/// Updates the control based on the control's .
///
@@ -215,32 +223,64 @@ namespace Avalonia.Controls.Presenters
{
var old = Child;
var content = Content;
- var result = this.MaterializeDataTemplate(content, ContentTemplate);
+ var result = content as IControl;
- if (old != null)
+ if (result == null)
{
- VisualChildren.Remove(old);
+ DataContext = content;
+
+ if (content != null)
+ {
+ if (old != null && _dataTemplate?.Match(content) == true)
+ {
+ 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());
+ }
+ }
+ }
+ else
+ {
+ _dataTemplate = null;
+ }
+ }
+ else
+ {
+ _dataTemplate = null;
}
- if (result != null)
+ if (result != old)
{
- if (!(content is IControl))
+ if (old != null)
{
- result.DataContext = content;
+ VisualChildren.Remove(old);
}
- Child = result;
+ if (result != null)
+ {
+ Child = result;
- if (result.Parent == null)
+ if (result.Parent == null)
+ {
+ ((ISetLogicalParent)result).SetParent((ILogical)this.TemplatedParent ?? this);
+ }
+
+ ((ISetInheritanceParent)result).SetParent(this);
+ VisualChildren.Add(result);
+ }
+ else
{
- ((ISetLogicalParent)result).SetParent((ILogical)this.TemplatedParent ?? this);
+ Child = null;
}
-
- VisualChildren.Add(result);
- }
- else
- {
- Child = null;
}
_createdChild = true;
diff --git a/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs b/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
index 9eff4243b1..df25733524 100644
--- a/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
+++ b/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
@@ -11,54 +11,6 @@ namespace Avalonia.Controls.Templates
///
public static class DataTemplateExtensions
{
- ///
- /// Materializes a piece of data based on a data template.
- ///
- /// The control materializing the data template.
- /// The data.
- ///
- /// An optional primary template that can will be tried before the
- /// in the tree are searched.
- ///
- /// The data materialized as a control.
- public static IControl MaterializeDataTemplate(
- this IControl control,
- object data,
- IDataTemplate primary = null)
- {
- if (data == null)
- {
- return null;
- }
- else
- {
- var asControl = data as IControl;
-
- if (asControl != null)
- {
- return asControl;
- }
- else
- {
- IDataTemplate template = control.FindDataTemplate(data, primary);
- IControl result;
-
- if (template != null)
- {
- result = template.Build(data);
- }
- else
- {
- result = FuncDataTemplate.Default.Build(data);
- }
-
- NameScope.SetNameScope((Control)result, new NameScope());
-
- return result;
- }
- }
- }
-
///
/// Find a data template that matches a piece of data.
///
diff --git a/src/Avalonia.Controls/Templates/FuncDataTemplate.cs b/src/Avalonia.Controls/Templates/FuncDataTemplate.cs
index 8ce3f69f36..bdf0732492 100644
--- a/src/Avalonia.Controls/Templates/FuncDataTemplate.cs
+++ b/src/Avalonia.Controls/Templates/FuncDataTemplate.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Reactive.Linq;
using System.Reflection;
namespace Avalonia.Controls.Templates
@@ -12,10 +13,25 @@ namespace Avalonia.Controls.Templates
public class FuncDataTemplate : FuncTemplate