From 8f7686fdfa21206216019b4e660d9cfe49b52dd0 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 d19fa977ee..e08a665785 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 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers 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 a59785cbbf..a959de20ba 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 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers public IXamlType WindowTransparencyLevel { get; } public IXamlType IReadOnlyListOfT { get; } public IXamlType ControlTemplate { get; } + public IXamlType IControlTemplate { get; } public IXamlType EventHandlerT { get; } public IXamlMethod GetClassProperty { get; } @@ -325,6 +326,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers 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 b2c697cbad..af291b6626 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; 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 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml 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