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 7d50e80c45..9bad038d42 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -108,6 +108,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers public IXamlType TextDecorations { get; } public IXamlType TextTrimming { get; } public IXamlType SetterBase { get; } + public IXamlType Setter { get; } public IXamlType IStyle { get; } public IXamlType StyleInclude { get; } public IXamlType ResourceInclude { get; } @@ -297,6 +298,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers TextDecorations = cfg.TypeSystem.GetType("Avalonia.Media.TextDecorations"); TextTrimming = cfg.TypeSystem.GetType("Avalonia.Media.TextTrimming"); SetterBase = cfg.TypeSystem.GetType("Avalonia.Styling.SetterBase"); + Setter = cfg.TypeSystem.GetType("Avalonia.Styling.Setter"); IStyle = cfg.TypeSystem.GetType("Avalonia.Styling.IStyle"); StyleInclude = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Styling.StyleInclude"); ResourceInclude = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Styling.ResourceInclude"); diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs index 51675bbb83..21a3f4eae2 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs @@ -85,10 +85,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions { return transformed; } - + var lastElement = transformed.Elements.LastOrDefault(); - if (parentNode.Property?.Getter?.ReturnType == context.GetAvaloniaTypes().ICommand && lastElement is XamlIlClrMethodPathElementNode methodPathElement) + if (GetPropertyType(context, parentNode) == context.GetAvaloniaTypes().ICommand && lastElement is XamlIlClrMethodPathElementNode methodPathElement) { IXamlMethod executeMethod = methodPathElement.Method; IXamlMethod canExecuteMethod = executeMethod.DeclaringType.FindMethod(new FindMethodMethodSignature($"Can{executeMethod.Name}", context.Configuration.WellKnownTypes.Boolean, context.Configuration.WellKnownTypes.Object)); @@ -110,6 +110,29 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions return transformed; } + private static IXamlType GetPropertyType(AstTransformationContext context, XamlPropertyAssignmentNode node) + { + var setterType = context.GetAvaloniaTypes().Setter; + + if (node.Property.DeclaringType == setterType && node.Property.Name == "Value") + { + // The property is a Setter.Value property. We need to get the type of the property that the Setter.Value property is setting. + var setter = context.ParentNodes() + .SkipWhile(x => x != node) + .OfType() + .Take(1) + .FirstOrDefault(x => x.Type.GetClrType() == setterType); + var propertyAssignment = setter?.Children.OfType() + .FirstOrDefault(x => x.Property.GetClrProperty().Name == "Property"); + var property = propertyAssignment?.Values.FirstOrDefault() as IXamlIlAvaloniaPropertyNode; + + if (property.AvaloniaPropertyType is { } propertyType) + return propertyType; + } + + return node.Property?.Getter?.ReturnType; + } + private static XamlIlBindingPathNode TransformBindingPath(AstTransformationContext context, IXamlLineInfo lineInfo, Func startTypeResolver, IXamlType selfType, IEnumerable bindingExpression) { List transformNodes = new List(); diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs index b48b4508e3..5e0813c9e6 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs @@ -1958,6 +1958,36 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions } } + [Fact] + public void Binding_Method_To_Command_In_Style_Works() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + + + +