Browse Source

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
Julien Lebosquain 1 năm trước cách đây
mục cha
commit
d5fdeb3d3a

+ 19 - 3
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<XamlAstXamlPropertyValueNode>()
-                .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<XamlAstTextNode>().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 _))

+ 23 - 3
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(
+                    $"""
+                     <Style Selector="Button" xmlns="https://github.com/avaloniaui">
+                         <Setter Property="{propertyName}">
+                             <Binding />
+                         </Setter>
+                     </Style>
+                     """);
+                var setter = (Setter)style.Setters.First();
+
+                Assert.IsType<Binding>(setter.Value);
+            }
+        }
+
         [Fact]
         public void Xml_Value_Should_Be_Assigned_To_Setter_Value()
         {