From d5fdeb3d3acec828ea9ab42fb9399dc2e36d546f Mon Sep 17 00:00:00 2001 From: Julien Lebosquain Date: Wed, 18 Sep 2024 06:44:51 +0200 Subject: [PATCH] Fix parsing of XAML setters when the child isn't a text node (#17044) * Added failing XAML test for binding inside setters * Fixed wrong XAML parsing of child value in setters --- .../AvaloniaXamlIlSetterTransformer.cs | 22 +++++++++++++--- .../StyleTests.cs | 26 ++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs index aecc4b47de..6bd00ed0ba 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs @@ -80,9 +80,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers var valueProperty = on.Children .OfType() - .FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value" && p.Values.Count == 1 && p.Values[0] is XamlAstTextNode); - var textValue = valueProperty?.Values.FirstOrDefault() as XamlAstTextNode - ?? on.Children.OfType().FirstOrDefault(); + .FirstOrDefault(p => p.Property.GetClrProperty().Name == "Value"); + + XamlAstTextNode? textValue = null; + + if (valueProperty is not null) + { + if (valueProperty.Values.Count == 1) + textValue = valueProperty.Values[0] as XamlAstTextNode; + } + else + { + var nonPropertyChildren = on.Children + .Where(child => child is not XamlAstXamlPropertyValueNode) + .ToArray(); + + if (nonPropertyChildren.Length == 1) + textValue = nonPropertyChildren[0] as XamlAstTextNode; + } + if (textValue is not null && XamlTransformHelpers.TryGetCorrectlyTypedValue(context, textValue, propType, out _)) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs index 2a80c39d2f..faf0bd9cb0 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs @@ -1,8 +1,7 @@ using System.Linq; -using System.Reactive.Linq; using Avalonia.Controls; using Avalonia.Data; -using Avalonia.PropertyStore; +using Avalonia.Layout; using Avalonia.Styling; using Avalonia.UnitTests; using Xunit; @@ -12,7 +11,7 @@ namespace Avalonia.Markup.Xaml.UnitTests public class StyleTests : XamlTestBase { [Fact] - public void Binding_Should_Be_Assigned_To_Setter_Value_Instead_Of_Bound() + public void Binding_As_Attribute_Should_Be_Assigned_To_Setter_Value_Instead_Of_Bound() { using (UnitTestApplication.Start(TestServices.MockPlatformWrapper)) { @@ -24,6 +23,27 @@ namespace Avalonia.Markup.Xaml.UnitTests } } + [Theory] + [InlineData(nameof(ContentControl.Content))] // standard property + [InlineData(nameof(Layoutable.Margin))] // primitive property which can be directly parsed + public void Binding_As_Element_Should_Be_Assigned_To_Setter_Value(string propertyName) + { + using (UnitTestApplication.Start(TestServices.MockPlatformWrapper)) + { + var style = (Style)AvaloniaRuntimeXamlLoader.Load( + $""" + + """); + var setter = (Setter)style.Setters.First(); + + Assert.IsType(setter.Value); + } + } + [Fact] public void Xml_Value_Should_Be_Assigned_To_Setter_Value() {