From 0aa035e58103f23cefc590e5437b20f7119b6aac Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 15 Jan 2016 16:49:43 +0100 Subject: [PATCH] Make sure AttachedToLogicalTree is only raised once. And add a check to make sure control is attached to logical tree before detach - I *think* this should always be the case, though there may be an edge case which triggers this exception, in which case do the same for DetachedFromLogicalTree as we've done for AttachedToLogicalTree here. --- src/Perspex.Controls/Control.cs | 34 +++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs index c4b974fe7e..a1fcce135e 100644 --- a/src/Perspex.Controls/Control.cs +++ b/src/Perspex.Controls/Control.cs @@ -406,19 +406,28 @@ namespace Perspex.Controls /// protected virtual void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { - if (_nameScope == null) + // This method can be called when a control is already attached to the logical tree + // in the following scenario: + // - ListBox gets assigned Items containing ListBoxItem + // - ListBox makes ListBoxItem a logical child + // - ListBox template gets applied; making its Panel get attached to logical tree + // - That AttachedToLogicalTree signal travels down to the ListBoxItem + if (!_isAttachedToLogicalTree) { - _nameScope = NameScope.GetNameScope(this) ?? ((Control)Parent)?._nameScope; - } + if (_nameScope == null) + { + _nameScope = NameScope.GetNameScope(this) ?? ((Control)Parent)?._nameScope; + } - if (Name != null) - { - _nameScope?.Register(Name, this); - } + if (Name != null) + { + _nameScope?.Register(Name, this); + } - _isAttachedToLogicalTree = true; - PerspexLocator.Current.GetService()?.ApplyStyles(this); - AttachedToLogicalTree?.Invoke(this, e); + _isAttachedToLogicalTree = true; + PerspexLocator.Current.GetService()?.ApplyStyles(this); + AttachedToLogicalTree?.Invoke(this, e); + } foreach (var child in LogicalChildren.OfType()) { @@ -436,6 +445,11 @@ namespace Perspex.Controls /// protected virtual void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) { + if (!_isAttachedToLogicalTree) + { + throw new Exception("Logic error: Control is not attached to logical tree"); + } + if (Name != null) { _nameScope?.Unregister(Name);