|
|
@@ -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;
|