Przeglądaj źródła

[XAMLX] Propagate TypeConverters from the original CLR property to avalonia property (#19727)

Nikita Tsukanov 2 tygodni temu
rodzic
commit
d0974ca7a6

+ 1 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs

@@ -224,6 +224,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
             }
 
             Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field));
+            TypeConverters = original.TypeConverters;
         }
 
         abstract class AvaloniaPropertyCustomSetter : IXamlILOptimizedEmitablePropertySetter, IEquatable<AvaloniaPropertyCustomSetter>

+ 51 - 0
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

@@ -458,6 +458,23 @@ namespace Avalonia.Markup.Xaml.UnitTests
             Assert.Equal(RuntimeXamlDiagnosticSeverity.Warning, warning.Severity);
             Assert.Equal("AVLN2208", warning.Id);
         }
+        
+        [Fact]
+        public void Type_Converters_Should_Work_When_Specified_With_Attributes_On_Avalonia_Properties()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+
+                var parsed = (XamlIlClassWithTypeConverterOnAvaloniaProperty)
+                    AvaloniaRuntimeXamlLoader.Parse(@"
+<XamlIlClassWithTypeConverterOnAvaloniaProperty
+    xmlns='clr-namespace:Avalonia.Markup.Xaml.UnitTests;assembly=Avalonia.Markup.Xaml.UnitTests' 
+    MyProp='a,b,c'/>",
+                        typeof(XamlIlBugTestsEventHandlerCodeBehind).Assembly);
+            
+                Assert.Equal((IEnumerable<string>)["a", "b", "c"], parsed.MyProp.Select(x => x.Value));
+            }
+        }
     }
 
     public class XamlIlBugTestsEventHandlerCodeBehind : Window
@@ -554,4 +571,38 @@ namespace Avalonia.Markup.Xaml.UnitTests
     {
         public int Count { get; set; }= 5;
     }
+
+    public class XamlIlClassWithTypeConverterOnAvaloniaProperty : AvaloniaObject
+    {
+        public class MyType(string value)
+        {
+            public string Value => value;
+        }
+        
+        public class MyTypeConverter : TypeConverter
+        {
+            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+            {
+                return sourceType == typeof(string);
+            }
+
+            public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+            {
+                if (value is string s)
+                    return s.Split([','], StringSplitOptions.RemoveEmptyEntries).Select(x => new MyType(x.Trim()));
+                return base.ConvertFrom(context, culture, value);
+            }
+        }
+
+        public static readonly StyledProperty<IEnumerable<MyType>> MyPropProperty = AvaloniaProperty.Register<XamlIlClassWithTypeConverterOnAvaloniaProperty, IEnumerable<MyType>>(
+            "MyProp");
+
+        [TypeConverter(typeof(MyTypeConverter))]
+        public IEnumerable<MyType> MyProp
+        {
+            get => GetValue(MyPropProperty);
+            set => SetValue(MyPropProperty, value);
+        }
+        
+    }
 }