From 766a814f4e03afa0d99ad33e153d6502501a1c5a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 5 Mar 2016 17:18:02 +0100 Subject: [PATCH] Check for correct state on attach/detach to tree. Make sure that if we're attached to a logical tree, we can invoke DetachedFromLogicalTree when Parent is set to null. This also has a side effect in that Parent will now be non-null when DetachedFromLogicalTree is called. --- src/Perspex.Base/Perspex.Base.csproj | 1 + src/Perspex.Base/PerspexInternalException.cs | 22 +++++++++++++++ src/Perspex.Controls/Control.cs | 28 +++++++++++++------- 3 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/Perspex.Base/PerspexInternalException.cs diff --git a/src/Perspex.Base/Perspex.Base.csproj b/src/Perspex.Base/Perspex.Base.csproj index dd41f12e9e..9a6acd4048 100644 --- a/src/Perspex.Base/Perspex.Base.csproj +++ b/src/Perspex.Base/Perspex.Base.csproj @@ -63,6 +63,7 @@ + diff --git a/src/Perspex.Base/PerspexInternalException.cs b/src/Perspex.Base/PerspexInternalException.cs new file mode 100644 index 0000000000..5ab4341e1a --- /dev/null +++ b/src/Perspex.Base/PerspexInternalException.cs @@ -0,0 +1,22 @@ +// 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; + +namespace Perspex +{ + /// + /// Exception signifying an internal logic error in Perspex. + /// + public class PerspexInternalException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// The exception message. + public PerspexInternalException(string message) + : base(message) + { + } + } +} diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs index 6aa7359783..eb096e2f0f 100644 --- a/src/Perspex.Controls/Control.cs +++ b/src/Perspex.Controls/Control.cs @@ -391,22 +391,32 @@ namespace Perspex.Controls throw new InvalidOperationException("The Control already has a parent."); } - InheritanceParent = parent as PerspexObject; - _parent = (IControl)parent; + if (_isAttachedToLogicalTree) + { + var oldRoot = FindStyleRoot(old); - var root = FindStyleRoot(old); + if (oldRoot == null) + { + throw new PerspexInternalException("Was attached to logical tree but cannot find root."); + } - if (root != null) - { - var e = new LogicalTreeAttachmentEventArgs(root); + var e = new LogicalTreeAttachmentEventArgs(oldRoot); OnDetachedFromLogicalTree(e); } - root = FindStyleRoot(this); + InheritanceParent = parent as PerspexObject; + _parent = (IControl)parent; - if (root != null) + if (_parent is IStyleRoot || _parent?.IsAttachedToLogicalTree == true) { - var e = new LogicalTreeAttachmentEventArgs(root); + var newRoot = FindStyleRoot(this); + + if (newRoot == null) + { + throw new PerspexInternalException("Parent is atttached to logical tree but cannot find root."); + } + + var e = new LogicalTreeAttachmentEventArgs(newRoot); OnAttachedToLogicalTree(e); }