From e6fda91d961633a9181e600dbdee47d1cb0dc897 Mon Sep 17 00:00:00 2001 From: Julien Lebosquain Date: Tue, 5 Nov 2024 23:33:19 +0100 Subject: [PATCH] Fix TemplateBinding in custom IControlTemplate implementations (#17427) * Add failing test for TemplateBinding inside custom control template * Fix TemplateBinding XAML compilation error for custom IControlTemplate --------- Co-authored-by: Max Katz --- ...olTemplateTargetTypeMetadataTransformer.cs | 2 +- .../AvaloniaXamlIlWellKnownTypes.cs | 2 + .../Xaml/ControlTemplateTests.cs | 53 +++++++++++++++++-- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs index d19fa977eea..e08a665785f 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs @@ -11,7 +11,7 @@ class AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer : IXamlAstTrans public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) { if (!(node is XamlAstObjectNode on - && on.Type.GetClrType() == context.GetAvaloniaTypes().ControlTemplate)) + && context.GetAvaloniaTypes().IControlTemplate.IsAssignableFrom(on.Type.GetClrType()))) return node; var tt = on.Children.OfType().FirstOrDefault(ch => ch.Property.GetClrProperty().Name == "TargetType"); diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs index 679938e504d..6dce6610880 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -129,6 +129,7 @@ sealed class AvaloniaXamlIlWellKnownTypes public IXamlType WindowTransparencyLevel { get; } public IXamlType IReadOnlyListOfT { get; } public IXamlType ControlTemplate { get; } + public IXamlType IControlTemplate { get; } public IXamlType EventHandlerT { get; } sealed internal class InteractivityWellKnownTypes @@ -324,6 +325,7 @@ public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) Style = cfg.TypeSystem.GetType("Avalonia.Styling.Style"); ControlTheme = cfg.TypeSystem.GetType("Avalonia.Styling.ControlTheme"); ControlTemplate = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Templates.ControlTemplate"); + IControlTemplate = cfg.TypeSystem.GetType("Avalonia.Controls.Templates.IControlTemplate"); IReadOnlyListOfT = cfg.TypeSystem.GetType("System.Collections.Generic.IReadOnlyList`1"); EventHandlerT = cfg.TypeSystem.GetType("System.EventHandler`1"); Interactivity = new InteractivityWellKnownTypes(cfg); diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs index b2c697cbad2..af291b6626d 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs @@ -6,10 +6,12 @@ using Avalonia.Controls.Metadata; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; +using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Diagnostics; using Avalonia.Markup.Xaml.Templates; using Avalonia.Media; +using Avalonia.Metadata; using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; @@ -437,13 +439,47 @@ public void ControlTemplate_Outputs_Error_When_Missing_TemplatePart_Nested_ItemT Assert.Equal(RuntimeXamlDiagnosticSeverity.Info, warning.Severity); Assert.Contains("'PART_MainContentBorder'", warning.Title); } + +#nullable enable + + [Fact] + public void Custom_ControlTemplate_Allows_TemplateBindings() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var window = (Window)AvaloniaRuntimeXamlLoader.Load( + """ + + + + """); + var button = Assert.IsType