diff --git a/src/Perspex.Controls/ContentControl.cs b/src/Perspex.Controls/ContentControl.cs
index e8b52a2948..b6cc7bab95 100644
--- a/src/Perspex.Controls/ContentControl.cs
+++ b/src/Perspex.Controls/ContentControl.cs
@@ -16,7 +16,7 @@ namespace Perspex.Controls
///
/// Displays according to a .
///
- public class ContentControl : TemplatedControl, IContentControl
+ public class ContentControl : TemplatedControl, IContentControl, IContentPresenterHost
{
///
/// Defines the property.
@@ -57,7 +57,7 @@ namespace Perspex.Controls
///
/// Gets the presenter from the control's template.
///
- public ContentPresenter Presenter
+ public IContentPresenter Presenter
{
get;
private set;
@@ -82,14 +82,9 @@ namespace Perspex.Controls
}
///
- protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
+ void IContentPresenterHost.RegisterContentPresenter(IContentPresenter presenter)
{
- base.OnTemplateApplied(e);
-
- // We allow ContentControls without ContentPresenters in the template. This can be
- // useful for e.g. a simple ToggleButton that displays an image. There's no need to
- // have a ContentPresenter in the visual tree for that.
- Presenter = e.NameScope.Find("PART_ContentPresenter");
+ Presenter = presenter;
}
}
}
diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj
index a0ea1e4084..92269f9108 100644
--- a/src/Perspex.Controls/Perspex.Controls.csproj
+++ b/src/Perspex.Controls/Perspex.Controls.csproj
@@ -57,6 +57,7 @@
+
diff --git a/src/Perspex.Controls/Presenters/ContentPresenter.cs b/src/Perspex.Controls/Presenters/ContentPresenter.cs
index fbc2300d02..223dca8088 100644
--- a/src/Perspex.Controls/Presenters/ContentPresenter.cs
+++ b/src/Perspex.Controls/Presenters/ContentPresenter.cs
@@ -34,6 +34,7 @@ namespace Perspex.Controls.Presenters
static ContentPresenter()
{
ContentProperty.Changed.AddClassHandler(x => x.ContentChanged);
+ TemplatedParentProperty.Changed.AddClassHandler(x => x.TemplatedParentChanged);
}
///
@@ -146,5 +147,10 @@ namespace Perspex.Controls.Presenters
_createdChild = false;
InvalidateMeasure();
}
+
+ private void TemplatedParentChanged(PerspexPropertyChangedEventArgs e)
+ {
+ (e.NewValue as IContentPresenterHost)?.RegisterContentPresenter(this);
+ }
}
}
diff --git a/src/Perspex.Controls/Presenters/IContentPresenterHost.cs b/src/Perspex.Controls/Presenters/IContentPresenterHost.cs
new file mode 100644
index 0000000000..137742a080
--- /dev/null
+++ b/src/Perspex.Controls/Presenters/IContentPresenterHost.cs
@@ -0,0 +1,27 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Styling;
+
+namespace Perspex.Controls.Presenters
+{
+ ///
+ /// Represents a control which hosts a content presenter.
+ ///
+ ///
+ /// This interface is implemented by which usually contains a
+ /// and exposes it through its
+ /// property. ContentPresenters can be within
+ /// nested templates or in popups and so are not necessarily created immediately when the
+ /// parent control's template is instantiated so they register themselves using this
+ /// interface.
+ ///
+ public interface IContentPresenterHost : ITemplatedControl
+ {
+ ///
+ /// Registers an with a host control.
+ ///
+ /// The content presenter.
+ void RegisterContentPresenter(IContentPresenter presenter);
+ }
+}
diff --git a/tests/Perspex.Controls.UnitTests/ContentControlTests.cs b/tests/Perspex.Controls.UnitTests/ContentControlTests.cs
index a8fc9d124c..979a0b4bab 100644
--- a/tests/Perspex.Controls.UnitTests/ContentControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ContentControlTests.cs
@@ -28,7 +28,7 @@ namespace Perspex.Controls.UnitTests
target.Content = "Foo";
target.Template = GetTemplate();
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
var child = ((IVisual)target).VisualChildren.Single();
Assert.IsType(child);
@@ -71,7 +71,7 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = child;
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
var contentPresenter = child.GetVisualParent();
Assert.Equal(target, contentPresenter.TemplatedParent);
@@ -86,7 +86,7 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = child;
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.Null(child.TemplatedParent);
}
@@ -117,7 +117,7 @@ namespace Perspex.Controls.UnitTests
target.Content = "Foo";
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
var child = target.Presenter.Child;
@@ -157,7 +157,7 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = child;
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.True(called);
}
@@ -172,12 +172,12 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = child;
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
((ILogical)target).LogicalChildren.CollectionChanged += (s, e) => called = true;
target.Content = null;
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.True(called);
}
@@ -193,7 +193,7 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = child1;
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
((ILogical)target).LogicalChildren.CollectionChanged += (s, e) => called = true;
@@ -210,13 +210,13 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
target.Content = "Foo";
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.Equal("Foo", ((TextBlock)target.Presenter.Child).Text);
target.Content = "Bar";
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.Equal("Bar", ((TextBlock)target.Presenter.Child).Text);
}
@@ -228,7 +228,7 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = "Foo";
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.Equal("Foo", target.Presenter.Child.DataContext);
}
@@ -241,7 +241,7 @@ namespace Perspex.Controls.UnitTests
target.Template = GetTemplate();
target.Content = new TextBlock();
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.Null(target.Presenter.Child.DataContext);
}
diff --git a/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs b/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs
index 57d0a0a7e7..e35f774ef5 100644
--- a/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs
+++ b/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs
@@ -28,7 +28,7 @@ namespace Perspex.Controls.UnitTests
};
root.ApplyTemplate();
- root.Presenter.UpdateChild();
+ ((ContentPresenter)root.Presenter).UpdateChild();
Assert.Same(root.Find("foo"), root.Content);
Assert.Same(root.Find("bar"), ((Border)root.Content).Child);
@@ -70,7 +70,7 @@ namespace Perspex.Controls.UnitTests
root.ApplyTemplate();
- Assert.Null(NameScope.GetNameScope(root.Presenter).Find("foo"));
+ Assert.Null(NameScope.GetNameScope((Control)root.Presenter).Find("foo"));
}
private class TestRoot : ContentControl, IRenderRoot, INameScope, IStyleRoot
diff --git a/tests/Perspex.Controls.UnitTests/ListBoxTests.cs b/tests/Perspex.Controls.UnitTests/ListBoxTests.cs
index eedd1a8682..fd58322b02 100644
--- a/tests/Perspex.Controls.UnitTests/ListBoxTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ListBoxTests.cs
@@ -42,7 +42,7 @@ namespace Perspex.Controls.UnitTests
var text = target.Presenter.Panel.Children
.OfType()
.Do(x => x.Template = ListBoxItemTemplate())
- .Do(x => { x.ApplyTemplate(); x.Presenter.UpdateChild(); })
+ .Do(x => { x.ApplyTemplate(); ((ContentPresenter)x.Presenter).UpdateChild(); })
.Select(x => x.Presenter.Child)
.OfType()
.Select(x => x.Text)
@@ -169,7 +169,7 @@ namespace Perspex.Controls.UnitTests
scrollViewer.ApplyTemplate();
// Then make the ScrollViewer create its child.
- scrollViewer.Presenter.UpdateChild();
+ ((ContentPresenter)scrollViewer.Presenter).UpdateChild();
// Now the ItemsPresenter should be reigstered, so apply its template.
target.Presenter.ApplyTemplate();
diff --git a/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs b/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs
index 4622d77159..47547837f9 100644
--- a/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs
+++ b/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs
@@ -231,7 +231,7 @@ namespace Perspex.Controls.UnitTests
scrollViewer.ApplyTemplate();
// Then make the ScrollViewer create its child.
- scrollViewer.Presenter.UpdateChild();
+ ((ContentPresenter)scrollViewer.Presenter).UpdateChild();
// Now the ItemsPresenter should be reigstered, so apply its template.
target.Presenter.ApplyTemplate();
diff --git a/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs b/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
index 91b523a299..b8beafa0c4 100644
--- a/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
+++ b/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Linq;
+using Moq;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
@@ -12,6 +13,17 @@ namespace Perspex.Controls.UnitTests.Presenters
{
public class ContentPresenterTests
{
+ [Fact]
+ public void Should_Register_With_Host_When_TemplatedParent_Set()
+ {
+ var host = new Mock();
+ var target = new ContentPresenter();
+
+ target.SetValue(Control.TemplatedParentProperty, host.Object);
+
+ host.Verify(x => x.RegisterContentPresenter(target));
+ }
+
[Fact]
public void Setting_Content_To_Control_Should_Set_Child()
{
diff --git a/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs b/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs
index f7758d15d2..dba82f976e 100644
--- a/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs
@@ -20,7 +20,7 @@ namespace Perspex.Controls.UnitTests
};
target.ApplyTemplate();
- target.Presenter.UpdateChild();
+ ((ContentPresenter)target.Presenter).UpdateChild();
Assert.IsType(target.Presenter.Child);
}