diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs index fc32084687..0d54e97bd9 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs @@ -15,14 +15,37 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers { if (node is XamlAstConstructableObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension)) { - IXamlType startType; - var parentDataContextNode = context.ParentNodes().OfType().FirstOrDefault(); - if (parentDataContextNode is null) + IXamlType startType = null; + var sourceProperty = binding.Children.OfType().FirstOrDefault(c => c.Property.Name == "Source"); + if ((sourceProperty?.Values.Count ?? 0) == 1) { - throw new XamlX.XamlParseException("Cannot parse a compiled binding without an explicit x:DataType directive to give a starting data type for bindings.", binding); + var sourceValue = sourceProperty.Values[0]; + switch (sourceValue) + { + case XamlAstTextNode textNode: + startType = textNode.Type?.GetClrType(); + break; + + case XamlMarkupExtensionNode extension: + startType = extension.Type?.GetClrType(); + break; + + case XamlStaticExtensionNode staticExtension: + startType = staticExtension.Type?.GetClrType(); + break; + } } - startType = parentDataContextNode.DataContextType; + if (startType == null) + { + var parentDataContextNode = context.ParentNodes().OfType().FirstOrDefault(); + if (parentDataContextNode is null) + { + throw new XamlX.XamlParseException("Cannot parse a compiled binding without an explicit x:DataType directive to give a starting data type for bindings.", binding); + } + + startType = parentDataContextNode.DataContextType; + } XamlIlBindingPathHelper.UpdateCompiledBindingExtension(context, binding, startType); } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs index 154c6a235c..6cb6e4e2d1 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs @@ -27,8 +27,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers } else if (prop.Name == "Source") { - return new AvaloniaSyntheticCompiledBindingProperty(node, - SyntheticCompiledBindingPropertyName.Source); + //return new AvaloniaSyntheticCompiledBindingProperty(node, + // SyntheticCompiledBindingPropertyName.Source); } } diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs index da39920eb3..17d2ea7ae9 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs @@ -32,6 +32,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions Mode = Mode, Priority = Priority, StringFormat = StringFormat, + Source = Source, DefaultAnchor = new WeakReference(GetDefaultAnchor(provider)) }; } @@ -52,6 +53,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor, bool enableDataValidation) { + if (Source != null) + { + return CreateSourceObserver( + Source, + Path.BuildExpression(enableDataValidation)); + } + if (Path.RawSource != null) { return CreateSourceObserver( @@ -77,5 +85,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions [ConstructorArgument("path")] public CompiledBindingPath Path { get; set; } + + public object Source { get; set; } } }