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 3250c7b8368..f9db15b0dbd 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -107,6 +107,7 @@ class AvaloniaXamlIlWellKnownTypes 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; } @@ -254,6 +255,7 @@ public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) 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 51675bbb837..21a3f4eae20 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 @@ private static XamlIlBindingPathNode TransformForTargetTyping(XamlIlBindingPathN { 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 @@ private static XamlIlBindingPathNode TransformForTargetTyping(XamlIlBindingPathN 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 7e25215f703..be8ccb704d1 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs @@ -1928,6 +1928,36 @@ public void Binding_Method_With_Parameter_To_Command_CanExecute_DependsOn() } } + [Fact] + public void Binding_Method_To_Command_In_Style_Works() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + + + +