From 4bdcb8eeeaab2f790245ddb70a5cfca3df7886f8 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 2 Jun 2022 10:34:34 +0200 Subject: [PATCH] Invalidate template control styles when Theme changes. --- .../Primitives/TemplatedControl.cs | 11 +++ .../Styling/StyledElementTests_Theming.cs | 75 ++++++++++++++----- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs index db029d38c0..a07dd9ae27 100644 --- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs +++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs @@ -365,6 +365,17 @@ namespace Avalonia.Controls.Primitives { } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == ThemeProperty) + { + foreach (var child in this.GetTemplateChildren()) + child.InvalidateStyles(); + } + } + /// /// Called when the control's template is applied. /// diff --git a/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs b/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs index 539f9e6576..0c0808987a 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs +++ b/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs @@ -8,6 +8,8 @@ using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; +#nullable enable + namespace Avalonia.Base.UnitTests.Styling; public class StyledElementTests_Theming @@ -45,6 +47,40 @@ public class StyledElementTests_Theming Assert.Null(target.Template); } + [Fact] + public void Theme_Is_Detached_From_Template_Controls_When_Theme_Property_Cleared() + { + using var app = UnitTestApplication.Start(TestServices.RealStyler); + + var theme = new ControlTheme + { + TargetType = typeof(ThemedControl), + Children = + { + new Style(x => x.Nesting().Template().OfType()) + { + Setters = + { + new Setter(Canvas.BackgroundProperty, Brushes.Red), + } + }, + } + }; + + var target = CreateTarget(theme); + target.Template = new FuncControlTemplate((o, n) => new Canvas()); + + var root = CreateRoot(target); + + var canvas = Assert.IsType(target.VisualChild); + Assert.Equal(canvas.Background, Brushes.Red); + + target.Theme = null; + + Assert.IsType(target.VisualChild); + Assert.Null(canvas.Background); + } + [Fact] public void Theme_Is_Applied_On_Layout_After_Theme_Property_Changes() { @@ -64,11 +100,11 @@ public class StyledElementTests_Theming Assert.Equal(border.Background, Brushes.Red); } - private static ThemedControl CreateTarget() + private static ThemedControl CreateTarget(ControlTheme? theme = null) { return new ThemedControl { - Theme = CreateTheme(), + Theme = theme ?? CreateTheme(), }; } @@ -132,33 +168,32 @@ public class StyledElementTests_Theming private static ControlTheme CreateTheme() { - var template = new FuncControlTemplate((o, n) => - new Border { Name = "PART_Border" }); + var template = new FuncControlTemplate((o, n) => new Border()); return new ControlTheme { TargetType = typeof(ThemedControl), Setters = - { - new Setter(ThemedControl.TemplateProperty, template), - }, - Children = - { - new Style(x => x.Nesting().Template().OfType()) { - Setters = - { - new Setter(Border.BackgroundProperty, Brushes.Red), - } + new Setter(ThemedControl.TemplateProperty, template), }, - new Style(x => x.Nesting().Class("foo").Template().OfType()) + Children = { - Setters = + new Style(x => x.Nesting().Template().OfType()) { - new Setter(Border.BackgroundProperty, Brushes.Green), - } - }, - } + Setters = + { + new Setter(Border.BackgroundProperty, Brushes.Red), + } + }, + new Style(x => x.Nesting().Class("foo").Template().OfType()) + { + Setters = + { + new Setter(Border.BackgroundProperty, Brushes.Green), + } + }, + } }; }