Browse Source

Throw exception if TopLevel added as child.

Closes #262.
Steven Kirk 10 years ago
parent
commit
663e760fda
2 changed files with 40 additions and 11 deletions
  1. 9 0
      src/Perspex.Controls/TopLevel.cs
  2. 31 11
      tests/Perspex.Controls.UnitTests/TopLevelTests.cs

+ 9 - 0
src/Perspex.Controls/TopLevel.cs

@@ -286,6 +286,15 @@ namespace Perspex.Controls
             PlatformImpl.Invalidate(new Rect(clientSize));
         }
 
+        /// <inheritdoc/>
+        protected override void OnAttachedToVisualTree(IRenderRoot root)
+        {
+            base.OnAttachedToVisualTree(root);
+
+            throw new InvalidOperationException(
+                $"Control '{GetType().Name}' is a top level control and cannot be added as a child.");
+        }
+
         /// <summary>
         /// Tries to get a service from an <see cref="IPerspexDependencyResolver"/>, throwing an
         /// exception if not found.

+ 31 - 11
tests/Perspex.Controls.UnitTests/TopLevelTests.cs

@@ -1,6 +1,7 @@
 // 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 System;
 using System.Reactive;
 using System.Reactive.Subjects;
 using Moq;
@@ -98,11 +99,7 @@ namespace Perspex.Controls.UnitTests
 
                 var target = new TestTopLevel(impl.Object)
                 {
-                    Template = new ControlTemplate<TestTopLevel>(x =>
-                        new ContentPresenter
-                        {
-                            [~ContentPresenter.ContentProperty] = x[~ContentControl.ContentProperty],
-                        }),
+                    Template = CreateTemplate(),
                     Content = new TextBlock
                     {
                         Width = 321,
@@ -128,11 +125,7 @@ namespace Perspex.Controls.UnitTests
 
                 var target = new TestTopLevel(impl.Object)
                 {
-                    Template = new ControlTemplate<TestTopLevel>(x =>
-                        new ContentPresenter
-                        {
-                            [~ContentPresenter.ContentProperty] = x[~ContentControl.ContentProperty],
-                        }),
+                    Template = CreateTemplate(),
                     Content = new TextBlock
                     {
                         Width = 321,
@@ -304,6 +297,34 @@ namespace Perspex.Controls.UnitTests
             }
         }
 
+        [Fact]
+        public void Adding_Top_Level_As_Child_Should_Throw_Exception()
+        {
+            using (PerspexLocator.EnterScope())
+            {
+                RegisterServices();
+
+                var impl = new Mock<ITopLevelImpl>();
+                impl.SetupAllProperties();
+                var target = new TestTopLevel(impl.Object);
+                var child = new TestTopLevel(impl.Object);
+
+                target.Template = CreateTemplate();
+                target.Content = child;
+
+                Assert.Throws<InvalidOperationException>(() => target.ApplyTemplate());
+            }
+        }
+
+        private ControlTemplate<TestTopLevel> CreateTemplate()
+        {
+            return new ControlTemplate<TestTopLevel>(x =>
+                new ContentPresenter
+                {
+                    [!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty],
+                });
+        }
+
         private void RegisterServices()
         {
             var fixture = new Fixture().Customize(new AutoMoqCustomization());
@@ -319,7 +340,6 @@ namespace Perspex.Controls.UnitTests
 
             globalStyles.Setup(x => x.Styles).Returns(theme);
 
-
             PerspexLocator.CurrentMutable
                 .Bind<IInputManager>().ToConstant(new Mock<IInputManager>().Object)
                 .Bind<IFocusManager>().ToConstant(new Mock<IFocusManager>().Object)