From bdaf4a2046b776c16135b5ef47864b25d2005e83 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 13 Dec 2017 15:41:27 -0600 Subject: [PATCH 1/4] Fix #1182. --- src/Avalonia.Controls/Control.cs | 14 ++++++++----- src/Avalonia.Controls/Primitives/PopupRoot.cs | 8 +++++++- .../ControlTests_Resources.cs | 16 +++++++++++++++ .../Primitives/PopupRootTests.cs | 20 +++++++++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index 6e1e1a05f1..89721e2e05 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -487,11 +487,6 @@ namespace Avalonia.Controls void ILogical.NotifyResourcesChanged(ResourcesChangedEventArgs e) { ResourcesChanged?.Invoke(this, new ResourcesChangedEventArgs()); - - foreach (var child in LogicalChildren) - { - child.NotifyResourcesChanged(e); - } } /// @@ -536,6 +531,15 @@ namespace Avalonia.Controls } _parent = (IControl)parent; + + if (old != null) + { + old.ResourcesChanged -= ThisResourcesChanged; + } + if (_parent != null) + { + _parent.ResourcesChanged += ThisResourcesChanged; + } ((ILogical)this).NotifyResourcesChanged(new ResourcesChangedEventArgs()); if (_parent is IStyleRoot || _parent?.IsAttachedToLogicalTree == true || this is IStyleRoot) diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index 00d43500c3..b0b0659f63 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -8,6 +8,7 @@ using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.Media; using Avalonia.Platform; +using Avalonia.Styling; using Avalonia.VisualTree; using JetBrains.Annotations; @@ -16,7 +17,7 @@ namespace Avalonia.Controls.Primitives /// /// The root window of a . /// - public class PopupRoot : WindowBase, IInteractive, IHostedVisualTreeRoot, IDisposable + public class PopupRoot : WindowBase, IInteractive, IHostedVisualTreeRoot, IDisposable, IResourceNode { private IDisposable _presenterSubscription; @@ -66,6 +67,11 @@ namespace Avalonia.Controls.Primitives /// IVisual IHostedVisualTreeRoot.Host => Parent; + /// + /// Gets the styling parent of the popup root. + /// + IResourceNode IResourceNode.ResourceParent => Parent; + /// public void Dispose() => PlatformImpl?.Dispose(); diff --git a/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs b/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs index 6a6cb48001..6acd224fe2 100644 --- a/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs +++ b/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs @@ -204,6 +204,22 @@ namespace Avalonia.Controls.UnitTests Assert.True(raised); } + [Fact] + public void Setting_Logical_Parent_Subscribes_To_Parents_ResourceChanged_Event() + { + var parent = new ContentControl(); + var child = new Border(); + + ((ISetLogicalParent)child).SetParent(parent); + var raisedOnChild = false; + + child.ResourcesChanged += (_, __) => raisedOnChild = true; + + parent.Resources.Add("foo", "bar"); + + Assert.True(raisedOnChild); + } + private IControlTemplate ContentControlTemplate() { return new FuncControlTemplate(x => diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index b3f91ce937..68a1f1d90f 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -7,6 +7,7 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.LogicalTree; +using Avalonia.Styling; using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; @@ -37,6 +38,25 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + [Fact] + public void PopupRoot_ResourceParent_Is_Popup() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var target = new TemplatedControlWithPopup + { + PopupContent = new Canvas(), + }; + + var root = new TestRoot { Child = target }; + + target.ApplyTemplate(); + target.Popup.Open(); + + Assert.Equal(target.Popup, ((IResourceNode)target.Popup.PopupRoot).ResourceParent); + } + } + [Fact] public void Attaching_PopupRoot_To_Parent_Logical_Tree_Raises_DetachedFromLogicalTree_And_AttachedToLogicalTree() { From 8bcd07730a4fe557e9c308937a732a21c5042660 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 14 Dec 2017 22:06:56 -0600 Subject: [PATCH 2/4] Change StylingParent for Popup to be PopupRoot so local styles flow to it. --- src/Avalonia.Controls/Primitives/PopupRoot.cs | 4 ++-- tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs | 2 +- .../Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index b0b0659f63..927a54a838 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -17,7 +17,7 @@ namespace Avalonia.Controls.Primitives /// /// The root window of a . /// - public class PopupRoot : WindowBase, IInteractive, IHostedVisualTreeRoot, IDisposable, IResourceNode + public class PopupRoot : WindowBase, IInteractive, IHostedVisualTreeRoot, IDisposable, IStyleHost { private IDisposable _presenterSubscription; @@ -70,7 +70,7 @@ namespace Avalonia.Controls.Primitives /// /// Gets the styling parent of the popup root. /// - IResourceNode IResourceNode.ResourceParent => Parent; + IStyleRoot IStyleHost.StylingParent => Parent; /// public void Dispose() => PlatformImpl?.Dispose(); diff --git a/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs b/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs index 6acd224fe2..9ee6e3e456 100644 --- a/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs +++ b/tests/Avalonia.Controls.UnitTests/ControlTests_Resources.cs @@ -168,7 +168,7 @@ namespace Avalonia.Controls.UnitTests target.Resources.Add("foo", "bar"); Assert.True(raisedOnTarget); - Assert.False(raisedOnPresenter); + Assert.True(raisedOnPresenter); Assert.True(raisedOnChild); } diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index 68a1f1d90f..d4b5d01a6b 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -39,7 +39,7 @@ namespace Avalonia.Controls.UnitTests.Primitives } [Fact] - public void PopupRoot_ResourceParent_Is_Popup() + public void PopupRoot_StylingParent_Is_Popup() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { @@ -53,7 +53,7 @@ namespace Avalonia.Controls.UnitTests.Primitives target.ApplyTemplate(); target.Popup.Open(); - Assert.Equal(target.Popup, ((IResourceNode)target.Popup.PopupRoot).ResourceParent); + Assert.Equal(target.Popup, ((IStyleHost)target.Popup.PopupRoot).StylingParent); } } From 23af42e4233444e556a6ab718036611c47eb70e3 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 14 Dec 2017 23:16:56 -0600 Subject: [PATCH 3/4] Fix explicit StylingParent definition. --- src/Avalonia.Controls/Primitives/PopupRoot.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index 927a54a838..507a085fed 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -70,7 +70,7 @@ namespace Avalonia.Controls.Primitives /// /// Gets the styling parent of the popup root. /// - IStyleRoot IStyleHost.StylingParent => Parent; + IStyleHost IStyleHost.StylingParent => Parent; /// public void Dispose() => PlatformImpl?.Dispose(); From b0d013ad25fbcbcfea0836cbed58cfc1424006ff Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 15 Dec 2017 12:25:20 -0600 Subject: [PATCH 4/4] Fix tests. --- .../Avalonia.Controls.UnitTests/Primitives/PopupTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index 06b3202a83..84ea717bab 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -15,6 +15,7 @@ using Avalonia.Styling; using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; +using Avalonia.Input; namespace Avalonia.Controls.UnitTests.Primitives { @@ -189,9 +190,11 @@ namespace Avalonia.Controls.UnitTests.Primitives { using (CreateServices()) { + var window = new Window(); var target = new Popup(); var child = new Control(); + window.Content = target; target.Open(); Assert.Single(target.PopupRoot.GetVisualChildren()); @@ -214,7 +217,8 @@ namespace Avalonia.Controls.UnitTests.Primitives { Content = new Border(), Template = new FuncControlTemplate(PopupContentControlTemplate), - } + }, + StylingParent = AvaloniaLocator.Current.GetService() }; target.ApplyTemplate(); @@ -306,7 +310,8 @@ namespace Avalonia.Controls.UnitTests.Primitives .Bind().ToFunc(() => globalStyles.Object) .Bind().ToConstant(new WindowingPlatformMock()) .Bind().ToTransient() - .Bind().ToFunc(() => renderInterface.Object); + .Bind().ToFunc(() => renderInterface.Object) + .Bind().ToConstant(new InputManager()); return result; }