Browse Source

Set ContentPresenter.DataContext in UpdateChild.

Thus delaying any changes that changing the data context would make
until we know we have the correct child.
pull/558/head
Steven Kirk 10 years ago
parent
commit
f3c7ea27a1
  1. 92
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  2. 1
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
  3. 4
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests.cs
  4. 1
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

92
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
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();

4
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
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();

Loading…
Cancel
Save