diff --git a/external/XamlX b/external/XamlX index ab84721302d..cbfec32876a 160000 --- a/external/XamlX +++ b/external/XamlX @@ -1 +1 @@ -Subproject commit ab84721302d6ed2b8b65315f3c54217693640348 +Subproject commit cbfec32876a79e855bd49da034214bbf2bf35b13 diff --git a/src/Avalonia.Base/Data/AssignBindingAttribute.cs b/src/Avalonia.Base/Data/AssignBindingAttribute.cs index 15bd32c7c21..45120157ad9 100644 --- a/src/Avalonia.Base/Data/AssignBindingAttribute.cs +++ b/src/Avalonia.Base/Data/AssignBindingAttribute.cs @@ -10,7 +10,7 @@ namespace Avalonia.Data /// Applying this attribute to a property indicates that the binding should be assigned to /// the property rather than bound. /// - [AttributeUsage(AttributeTargets.Property)] + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] public sealed class AssignBindingAttribute : Attribute { } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs index 7fd8d987b9f..0d4b6eceeff 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs @@ -204,12 +204,11 @@ class XamlIlAvaloniaProperty : XamlAstClrProperty, IXamlIlAvaloniaProperty public IXamlField AvaloniaProperty { get; } public XamlIlAvaloniaProperty(XamlAstClrProperty original, IXamlField field, AvaloniaXamlIlWellKnownTypes types) - :base(original, original.Name, original.DeclaringType, original.Getter, original.Setters) + :base(original, original.Name, original.DeclaringType, original.Getter, original.Setters, original.CustomAttributes) { var assignBinding = original.CustomAttributes.Any(ca => ca.Type.Equals(types.AssignBindingAttribute)); AvaloniaProperty = field; - CustomAttributes = original.CustomAttributes; if (!assignBinding) Setters.Insert(0, new BindingSetter(types, original.DeclaringType, field)); @@ -459,7 +458,7 @@ sealed class XamlIlAvaloniaClassProperty : XamlAstClrProperty, public XamlIlAvaloniaClassProperty(AvaloniaXamlIlWellKnownTypes types, string className, - IXamlLineInfo lineInfo) : base(lineInfo, className, types.Classes, null, null, null) + IXamlLineInfo lineInfo) : base(lineInfo, className, types.Classes, null) { Parameters = [types.XamlIlTypes.String]; _method = types.GetClassProperty; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/AssignBindingTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/AssignBindingTests.cs new file mode 100644 index 00000000000..114b626e639 --- /dev/null +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/AssignBindingTests.cs @@ -0,0 +1,62 @@ +#nullable enable + +using Avalonia.Controls; +using Avalonia.Data; +using Avalonia.UnitTests; +using Xunit; + +namespace Avalonia.Markup.Xaml.UnitTests.Xaml; + +public class AssignBindingTests : XamlTestBase +{ + [Fact] + public void AssignBinding_Works_With_Clr_Property() + { + using var app = UnitTestApplication.Start(TestServices.StyledWindow); + + var control = (AssignBindingTestControl)AvaloniaRuntimeXamlLoader.Load( + """ + + """); + + Assert.NotNull(control.ClrBinding); + } + + [Fact] + public void AssignBinding_Works_With_AttachedProperty() + { + using var app = UnitTestApplication.Start(TestServices.StyledWindow); + + var control = (Control)AvaloniaRuntimeXamlLoader.Load( + """ + + """); + + var binding = AssignBindingTestControl.GetAttachedBinding(control); + Assert.NotNull(binding); + } +} + +public sealed class AssignBindingTestControl : Control +{ + [AssignBinding] + public IBinding? ClrBinding { get; set; } + + public static readonly AttachedProperty AttachedBindingProperty = + AvaloniaProperty.RegisterAttached("AttachedBinding"); + + [AssignBinding] + public static IBinding? GetAttachedBinding(Control obj) + => obj.GetValue(AttachedBindingProperty); + + public static void SetAttachedBinding(Control obj, IBinding? value) + => obj.SetValue(AttachedBindingProperty, value); +}